1:闭包
闭包的定义 :是指有权访问另一个函数作用域中的变量的函数。创建闭包的常见方式,就是在一个函数内部创建另一个函数。
/** *闭包 :是指有权访问另一个函数作用域中的变量的函数。创建闭包的常见方式,就是在一个函数内部创建另一个函数。 * * 这两行代码访问了外部函数中的变量propertyName.即使这个内部函数被返回了,而且是在其他地方被调用了, * 但它仍然可以访问变量propertyName.之所以还能够访问这个变量,是因为内部函数的作用域包含 * createComparisonFunction()的作用域。 * * 当某个函数第一次被调用时,会创建一个执行环境(execution context)及相应的作用域链,并把作用域链赋值 * 给一个特殊的内部属性(即[Scope])。然后,使后,使用this、arguments和其他命名参数的值来初始化函数的 * 活动对象(activation object)。但在作用域,外部函数的活动对象始终处于第二位,外部函数的外部函数的 * 活动对象处于第三位,..直至作用域链终点的全局执行环境。 * * * 由于闭包会携带包含它的函数的作用域,因此会比其他函数占有用更多的内存。过度使用闭包可能会导致内存占用 * 过多,所以只在绝对必要时考虑使用闭包。 */ function createComparisonFunction(propertyName){ return function(object1,object2){ var value1=object1[propertyName]; //**** var value2=object2[propertyName]; //**** if(value1<value2){ return -1; }else if(value1>value2){ return 1; }else{ return 0; } } }
2:闭包与变量
作用域链的这种配置机制引出了一个值得注意的副作用,即闭包只能取得包含函数中任何变量的最后一个值 。因为闭包所保存的是整个变量对象、环境,而不是某个特殊的变量
/** * 闭包与变量 * * 作用域链的这种配置机制引出了一个值得注意的副作用,即闭包只能取得包含函数中任何变量的最后一个值 。 * 因为闭包所保存的是整个变量对象、环境,而不是某个特殊的变量。 */ function createFunctions(){ var result=new Array(); for(var i=0;i<10;i++){ result[i]=function(){ return i; } } return result; } var funcs=createFunctions(); //每个函数都输出10 for(var i=0;i<funcs.length;i++){ document.write(funcs[i]()+"<br/>"); } /** *但是可以创建另一个匿名函数强制让闭包的行为条例预期行为。 */ function createFunctions(){ var result=new Array(); for(var i=0;i<10;i++){ result[i]=function(num){ return function(){ return num; } }(i); } }
3:匿名函数(模仿块级作用域)
这种技术经常在全局作用域中被用在函数外部,从而限制向全局作用域中添加过多的变量和函数。一般来说,我们都应该以是少向全局作用域中添加变量和函数。在一个由很多开发人员共同参与的大型应用程序中,过多的全局变量和函数很容易导致命名冲突。而通过创建私有作用域,每个开发人员既可以使用自己的变量,又不必担心搞乱全局作用域。
/** *模仿块级作用域 * * 这种技术经常在全局作用域中被用在函数外部,从而限制向全局作用域中添加过多的变量和函数。 * 一般来说,我们都应该以是少向全局作用域中添加变量和函数。在一个由很多开发人员共同参与 * 的大型应用程序中,过多的全局变量和函数很容易导致命名冲突。而通过创建私有作用域,每个 * 开发人员既可以使用自己的变量,又不必担心搞乱全局作用域。 */ (function(){ //这里是块级作用域 })() //无论什么地方,只要临时需要一些变量,就可以使用私有作用域。 function outputNumbers(count){ (function(){ for(var i=0;i<count;i++){ alert(i); } })() alert(i); //导致一个错误。 } /** *这段代码在全局作用域中,其中变量now现在是匿名函数中的局部变量,而我们不必在全局作用域中创建它。 * 这种做法可以减少闭包占用的内存问题,因为没有指向匿名函数的引用,只要函数执行完毕,就可以立即 * 销毁其作用域了。 */ (function(){ var now=new Date(); if(now.getMonth()==0 && now.getDate()==1){ alert("Happy new year!"); } })
4:模块模式
道格拉斯所说的模块模式(module pattern)是为单例创建私有变量和特权方法。 这种模式在需要对单例进行某些初始化,同时又需要维护其私有变量时非常有用。
/** *模块模式 * 道格拉斯所说的模块模式(module pattern)是为单例创建私有变量和特权方法。 * 这种模式在需要对单例进行某些初始化,同时又需要维护其私有变量时非常有用。 */ var singleton=function(){ //私有变量和私有函数 var privateVariable=10; function privateFunction(){ return false; } //特权、公有方法和属性 return { publicProperty:true, publicMethod:function(){ privateVariable++; return privateFunction(); } } } /** *增强的模块模式 * 这种增强的模块模式适合那些单例必须是某种类型的实例,同时还必须添加某些属性和方法对其以增强的情况。 */ var singleton=function(){ //私有变量和私有函数 var privateVariable=10; function privateFunction(){ return false; } //创建对象 var object=new CustomType(); //添加特权/公有属性和方法 object.publicProperty=true; object.publicMethod=function(){ privateVariable++; return privateFunction(); }; //返回这个对象 return object; }