1.Javascript特殊的变量作用域。
变量的作用域无非就是两种:全局变量和局部变量。
Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量。
function f1() { var n = 999; } alert(n); // error没有变量n
函数内部声明变量的时候,一定要使用var命令。如果不用的话,你实际上声明了一个全局变量!
function f2() { n = 999; } f2(); alert(n); // 999
2.Javascript语言特有的"链式作用域"结构(chain scope),
子对象会一级一级地向上寻找所有父对象的变量。
父对象的所有变量,对子对象都是可见的,反之则不成立。
3.什么是闭包:
当内部函数在定义它的作用域的外部被引用时,就创建了该内部函数的闭包
这个不是闭包
function f3(x) { var temp = 3; function bar(y) { temp = temp + 1; alert(x + y + temp); } bar(10); } f3(2) //2+10+4=16; 不管执行多少次,都会alert 16,因为bar能访问foo的参数x,也能访问f3的变量tmp。这个不是闭包
闭包
function f4(x) { var temp = 3; return function (y) { temp = temp + 1; alert(x + y + temp); } } var bar = f4(2); // bar 现在是一个闭包 bar(10);//第一次16,第二次17,每次自动加1 f4(2)(10); //这个每次都是16,因为每次都是一个新的对象,这个对象是不存在的,与上面的区别是上面的已经存在。
function f5() { var n = 999; nAdd = function () { n += 1 } //nAdd前面没有使用var关键字,因此nAdd是一个全局变量,而不是局部变量 function f6() { alert(n); } return f6; } var result = f5(); result(); // 999 nAdd(); result(); // 1000 var name = "The Window"; var object = { name: "My Object", getNameFunc: function () { alert(this.name); //My Object return function () { return this.name; //当前的name,没有的话当成全局变量 }; } }; alert(object.getNameFunc()()); //The Window var name = "The Window"; var object = { name: "My Object", getNameFunc: function () { var that = this; return function () { return that.name; }; } }; alert(object.getNameFunc()());//My Object
4.闭包的注意点:
1)由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。
2)闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。