众所周知,JavaScript没有块级做用域,只有函数做用域。那就意味着定义在函数中的参数和变量在函数外部是不可见的,而在一个函数内部任何位置定义的变量,在该函数内部任何地方均可见。这带来的好处是内部函数能够访问定义它们的外部函数的参数和变量。javascript
首先,咱们来构造一个简单的对象。java
1 var testObj = { 2 value: 10, 3 add: function(inc){ 4 this.value += (typeof inc === "number") ? inc : 1; 5 } 6 }; 7 8 testObj.add(); 9 testObj.value; // 11 10 11 testObj.add(2); 12 testObj.value; // 13
这样写就有一个问题,value值不能保证不会被非法修改,能够按以下的方法进行修改。闭包
var testObj = (function(){ var value = 10; return { add: function(inc){ value += (typeof inc === "number") ? inc : 1; }, getValue: function(){ return value; } }; })(); testObj.add(); testObj.getValue(); // 11 testObj.add(2); testObj.getValue(); // 13
咱们能够通用调用一个函数的形式去初始化testObj,该函数会返回一个对象字面量,函数里定义了一个value变量,该变量对add和getValue方法老是可用的,但函数的做用域使得它对其余的程序来讲是不可见的。同时,咱们还能够得出一个结论,内部函数拥有比它的外部函数更长的生命周期。函数
咱们再继续看一个构造函数调用的例子。this
var MyObj = function(str){ this.status = str; }; MyObj.prototype.getStatus = function(){ return this.status; }; var obj = new MyObj("javascript"); obj.getStatus(); // "javascript"
这样写并无错,可是会有一点“画蛇添足”,为何要用一个getStatus方法去访问一个本能够直接访问到的属性呢?若是status是私有属性,那固然才有意义。spa
var obj = function(status){ return { getStatus: function(){ return status; } }; }; var myObj = obj("javascript"); myObj.getStatus(); // "javascript"
这里当咱们调用obj的时候,它返回包含getStatus方法的一个新对象,该对象的一个引用保存在myObj中,即便obj已经返回了,但getStatus方法仍然享有访问obj对象的status属性的特权。getStatus方法并非访问该参数的一个副本,它访问的就是该参数自己。这是可能的,由于该函数能够访问它被建立时所处的上下文环境,这被称为闭包。prototype