function getPrototyNames(o,/*optional*/ a){a = a || [];for(var p in o){a.push(p);}return a;} callerfunction callfunc(){if(callfunc.caller){alert(callfunc.caller.toString());}else{alert("没有函数调用");}}function handleCaller(){callfunc();}handleCaller();//返回 handlercallfunc();//没有函数调用,返回null,执行了《没有函数调用》 calleealert( (function (x) {if (x <= ) return ;return x * arguments.callee(x - );}()));// scope<script>var global = "global scope";//这个是全局的作用域function scope(){var scope = "local scope";//这个是局部的作用域return scope;//返回的scope,是局部的变量}</script> 1、:定义的全局变量也能在函数内部访问。当定义的局部变量和全局变量名字相同时,局部变量的就会隐藏全局变量,不会破坏全局变量的值。var scope = "global scope";function f(){var scope = "local scope";return scope;}alert(f());//local scopealert(scope);//global scope; 上面确实是很容易理解,对吧。<span style="line-height: .; font-family: verdana, Arial, Helvetica, sans-serif; font-size: px; background-color: rgb(, , );"> </span> scope = "global scope";function f(){scope = "local scope";return scope;}alert(f());//local scopealert(scope);//local scope 但是全局变量不使用var声明,也仅限非严格模式,如果使用严格模式的话,会报错误<script>"use strict";scope = "global scope";function f(){scope = "local scope";return scope;}alert(f());//local scopealert(scope);//local scope</script>
所以建议大家声明变量时,千万不要省略var,可以避免不必要的麻烦。
3、 声明提前,也是可以滴。什么叫什么提前。

<script>"use strict";scope;console.log(scope);var scope = "global scope";console.log(scope);</script>这个可能大家看出第一个打印undefined ,是呀还没有给他赋值, 下面赋值可定打印global scope了。
<script>"use strict";var scope = "global scope";function f() {console.log(scope);var scope = "local scope";console.log(scope);}f();</script>看到这段代码:如果你粗心大意的话,很有可能会写出错误的答案:<script>var g = "global scope";function f(){for(var i=;i<;i++){for(var j=;j<;j++){;}console.log(j);}console.log(i);}console.log(g);f();</script> 打印的结果是什么?
结果为什么会是这样,我开始的表情和你一样。

这时查看我让你记住的那句话。。。全局变量在程序中始终都是有定义的。局部变量在声明它的函数体以及其所嵌套的函数内始终是定义的。
确切的说函数的参数 也是属于局部变量的范畴。这句话也很重要!!!
那句话大概意思说,只要是在函数内部定义的变量,在整个函数内都是有效的。所以结果也就不难理解了。在回过头看我们的那个问题,你理解了吗?
作用链还有以下定义:
1、作用链是有一个全局对象组成。
2、在不包含嵌套的函数体内,作用链上有两个对象,第一个定义了函数参数和局部变量的对象,第二个是全局对象。
3、在一个嵌套的函数体内,作用链上至少包含三个对象。
当定以一个函数的时候,就会保存一个作用域链。
当调用这个函数时,它就会创建一个新的对象来存储它的局部变量,并将这个对象添加到保存的作用链上。同时创建一个新的更长的表示函数调用的作用链。
对于嵌套的函数,当调用外部函数时,内部函数又会重新定义一遍。因为每次调用外部函数的时候,作用链都是不同的。内部函数在每次定义的时候都有微妙的差别,每次调用的外部函数时,内部函数的代码都是相同的,而且关联的代码的作用域也是不同的。
闭包
搞了这么久终于要讲了,但是再将之前我们在来分析下作用域。
<script>var nameg="global"var g = function f() {console.log(name);function demo(){console.log("demo="+name);}var name = "";function demo() {var name = "";console.log("demo=" + name);}function demo() {console.log("demo=" + nameg);}demo();demo();demo();};g();</script> 我们按照作用链来分析:<script>function f(){var count = ;return { counter:function() {return count++;},reset:function(){return count = ;}}}var d = f();var c = f();console.log("d第一次调用:"+ d.counter());//console.log("c第一次调用:"+ c.counter());// 互不影响console.log("d第一次调用:"+ d.reset());//console.log("c第二次调调用"+ c.counter());//</script> 这个例子上大家可以看到,我做了一个计数和置零的操作。<body><script>function btnInit(){for(var i=;i<;i++){var btn = document.getElementById("btn" + i);btn.addEventListener("click",function() {alert("btn" + i);});}}window.onload= btnInit;</script><div><button id="btn">Btn</button><button id="btn">Btn</button><button id="btn">Btn</button><button id="btn">Btn</button></div></body> 点击运行,结果却是都是btn5;function btnInit(){for(var i=;i<;i++){(function (data_i) {var btn = document.getElementById("btn" + data_i);btn.addEventListener("click", function () {alert("btn" + data_i);});}(i));}} 看修改后的代码,首先执行第一次for,创建了一个对象,我们首先是执行匿名函数->data_i,未找到->function(data_i)找到,然后再次执行for有创建一个对象,闭包规则说的互不影响。所以能得出正确的结果。