转载

红皮书:函数表达式(七)

递归

function factorial(num){  if(num<=1){   return 1;  }else {   return num * arguments.callee(num-1);  } } console.log(factorial(4));  

闭包

闭包是指有权访问另一个函数作用域中的变量的函数。

  • 闭包与变量

作用域链的这种配置机制引出了一个值得注意的副作用,即闭包只能取得包含函数中任何变量的最后一个值。别忘了闭包所保存的是整个变量对象,而不是某个特殊的变量。

function createFunctions(){  var result = new Array();  for (var i=0; i<10; i++){   result[i] = function(){    return i;   }  }  return result; }  

我们可以通过创建另一个匿名函数强制让闭包的行为符合预期。

function createFunctions(){  var result = new Array();  for (var i=0; i<10; i++){   result[i] = function(num){    return function(){     return num;    };   }(i);  }  return result; }  
  • 关于this对象

在全局函数中,this等于window,而当函数被作为某个对象的方法调用时,this等于那个对象。不过,匿名函数的执行环境具有全局性,因此其this对象通常指向window。

var name = "The window"; var object = {  name: "My Object",  getNameFunc: function(){   return function(){    return this.name;   };  } }; console.log(object.getNameFunc()()); // The window  

不过,把外部作用域中的this对象保存在一个闭包能够访问到的变量里,就可以让闭包访问该对象了。

var name = "The window"; var object = {  name: "My Object",  getNameFunc: function(){   var that = this;   return function(){    return that.name;   };  } }; console.log(object.getNameFunc()()); // My Object   

内存泄露

function assignHandler(){                 var element=document.getElementById('someElement');                 element.onclick=function(){                     alert(element.id);                 }             } 

上述代码它所占用的内存不会永远消失。修改一下代码如下解决:

function assignHandler(){  var element = document.getElementById('someElement');  var id = element.id;  element.onclick = function(){      alert(id);  }  element = null;     }  

模仿块级作用域

用块级作用域(通常称为私用作用域)的匿名函数的语法如下所示:

(function(){ })(); 

私有变量

function add(num1,num2){     var sum=num1+num2;     return sum; } 

在这个函数内部,有三个私有变量:sum,num1,num2。在函数内部可以访问这几个变量。但是在函数外部则不能访问它们。如果在这个函数内部创建一个闭包,那么闭包可以通过自己的作用域链也可以访问这些变量。而利用这一点,就可以创建用于访问私有变量的公有方法。

我们把有权访问私有变量和私有函数的公有方法称为特权方法。有两种在对象上创建特权方法的方式。第一种是在构造函数中定义特权方法。基本模式如下:

function myObejct(){  //私有变量和私有函数  var privateVariable=10;  function privateFunction(){   return false;  }  //特权方法  this.publicMethod=function(){   privateVariable++;   return privateFunction();  } }  

利用私有和特权成员,可以隐藏那些不应该被直接修改的数据,例如:

function Person(name){  this.getName=function(){   return name;  }  this.setName=function(value){   name=value;  } } var person=new Person("Nicholas"); alert(person.getName());//Nicholas person.setName("Greg"); alert(person.getName());//Greg  
  • 静态私有变量

通过在私有作用域中定义私有变量或函数,同样也可以创建特权方法。其基本模式如下:

(function(){  //私有变量和私有函数  var privateVariable=10;  function privateFunction(){   return false;  }  //构造函数  MyObject=function(){  };  //公有/特权方法  MyObject.prototype.publicMethod=function(){   privateVariable++;   return privateFunction();  } })();  
  • 模块模式

模块模式是为单例创建私有变量和特权方法。所谓单例,指的就是只有一个实例的对象。按照惯例,js是以对象字面量的方式来创建单例对象的。

var singleton={     name:value,     method:function(){         //这里是方法的代码     } }; 

模块模式通过为单例添加私有变量和特权方法能够使其得到增强。其语法形式如下:

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;  

}();

正文到此结束
Loading...