闭包是指可以引用外部函数中的局部变量的函数,并致使外部函数调用后函数对象与局部变量没法及时销毁。函数是JavaScript中惟一拥有自身做用域的结构,所以闭包的建立依赖于函数。缓存
var Foo = function() { var name = 'staven'; this.getName = function() { return name; }; }; var foo = new Foo(); console.log(foo.name); //undefined console.log(foo.getName()); //staven
做用域链的这种配置机制引出了一个值得注意的反作用,即闭包只能取得包含函数中任何变量的最后一个值。闭包
for(var i = 0; i < 10; i++) { setTimeout(function() { console.log(i); //10次输出10 }, 1000); }
为了正确的得到循环序号,最好使用自执行匿名函数。app
for(var i = 0; i < 10; i++) { (function(e) { setTimeout(function() { console.log(e); }, 1000); })(i); }
匿名函数的执行环境具备全局性,所以其 this 对象一般指向 window(在经过 call()或 apply()改变函数执行环境的状况下, this 就会指向其余对象)。函数
var name = '全局'; var obj = { name: '局部', getName: function(){ var that = this; return function(){ return that.name; } } }; console.log(obj.getName()()); //局部
把外部做用域中的 this 对象保存在一个闭包可以访问到的变量里,就可让闭包访问该对象了。this
var name = "全局"; var obj = { name: "局部", getName: function() { var that = this; return function() { return that.name; }; } }; console.log(obj.getName()()); //"局部"
只要咱们临时须要一些变量,均可以使用块级做用域(私有做用域)。当匿名函数执行完毕,其做用域链当即销毁,从而能够减小闭包占用资源问题。prototype
(function($, window, document, undefined){ var name = "staven"; $.fn.getName = function(){ }; })(jQuery, window, document);
缓存数据、柯里化code
//利用闭包实现 var Book = (function(){ //静态私有变量 var bookNum = 0; //静态私有方法 function checkBook(name){ console.log("checking Book……"); } //建立类 function _book(newId, newName, newPrice){ if(this instanceof _book){ //私有变量 var name, price; //私有方法 function checkID(id){ console.log("checking id……"); } //特权方法 this.getName = function(){}; this.getPrice = function(){}; this.setName = function(){}; this.setPrice = function(){}; //公有属性 this.id = newId; //公有方法 this.copy = function() { console.log("copying……") }; bookNum++; if(bookNum > 100){ throw new Error('咱们仅出版100本书'); } //构造器 this.setName(name); this.setPrice(price); }else{ return new _book(newId, newName, newPrice); } } //构建原型 _book.prototype = { //静态共有属性 isJSBook:false, //静态共有方法 show:function(){ console.log("showing……"); } }; //返回类 return _book; })(); Book(21,'staven',23).show(); //showing…… Book(21,'staven',23).copy(); //copy…… var book = new Book(21,'staven',23); book.show(); //showing…… book.copy(); //copying……
因为闭包会携带包含它的函数的做用域,所以会比其余函数占用更多的内存。过分使用闭包可能会致使内存占用过多,建议只在绝对必要时再考虑使用闭包。对象