资讯专栏INFORMATION COLUMN

深究JavaScript——闭包

Dionysus_go / 1252人阅读

摘要:函数是中唯一拥有自身作用域的结构,因此闭包的创建依赖于函数。闭包中的匿名函数的执行环境具有全局性,因此其对象通常指向在通过或改变函数执行环境的情况下,就会指向其他对象。当匿名函数执行完毕,其作用域链立即销毁,从而可以减少闭包占用资源问题。

概念

  闭包是指能够引用外部函数中的局部变量的函数,并导致外部函数调用后函数对象与局部变量无法及时销毁。函数是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);
}

  为了正确的获得循环序号,最好使用自执行匿名函数。

for(var i = 0; i < 10; i++) {
    (function(e) {
        setTimeout(function() {
            console.log(e);  
        }, 1000);
    })(i);
}
闭包中的this

  匿名函数的执行环境具有全局性,因此其 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 对象保存在一个闭包能够访问到的变量里,就可以让闭包访问该对象了。

var name = "全局";
var obj = {
    name: "局部",
    getName: function() {
        var that = this;
        return function() {
            return that.name;
        };
    }
};
console.log(obj.getName()());  //"局部"
闭包的作用
模拟块级作用域:

  只要我们临时需要一些变量,都可以使用块级作用域(私有作用域)。当匿名函数执行完毕,其作用域链立即销毁,从而可以减少闭包占用资源问题。

(function($, window, document, undefined){
    var name = "staven";
    $.fn.getName = function(){
        
    };
})(jQuery, window, document);
在内存中保存变量:

  缓存数据、柯里化

模拟私有属性和私有方法:
//利用闭包实现
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…… 

  由于闭包会携带包含它的函数的作用域,因此会比其他函数占用更多的内存。过度使用闭包可能会导致内存占用过多,建议只在绝对必要时再考虑使用闭包。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/86833.html

相关文章

  • 初探 event loop

    摘要:事件循环了解知识点线程执行栈线程是单线程的语言可以单线程将理解为只有一条车道在车道里后面的车在等前面的车通过后才能通过即当前面的程序没有执行后面的程序也不能执行执行栈执行栈像车道被执行的程序会放入执行栈里但它的执行的顺序是后面进来的程序先执 事件循环 了解知识点 线程 执行栈 task queue web api macro task micro task 线程 javascrip...

    hsluoyz 评论0 收藏0
  • JavaScript深入系列15篇正式完结!

    摘要:写在前面深入系列共计篇已经正式完结,这是一个旨在帮助大家,其实也是帮助自己捋顺底层知识的系列。深入系列自月日发布第一篇文章,到月日发布最后一篇,感谢各位朋友的收藏点赞,鼓励指正。 写在前面 JavaScript 深入系列共计 15 篇已经正式完结,这是一个旨在帮助大家,其实也是帮助自己捋顺 JavaScript 底层知识的系列。重点讲解了如原型、作用域、执行上下文、变量对象、this、...

    fxp 评论0 收藏0
  • 10分钟了解Javascript-天码营

    摘要:然后将构造函数的原型设为,便实现了对象继承。首先,我们定义一个构造函数,并在其中定义一个局部变量。这里的是局部变量,其作用域仍然存在是闭包现象,而非对象属性。 Javascript是动态的,弱类型的,解释执行的程序设计语言。 Javascript极其灵活,支持多种程序设计范式:面向对象、指令式、函数式。JavaSCript最初被用于浏览器脚本,现在已经是所有主流浏览器的默认脚本语言。浏...

    trigkit4 评论0 收藏0
  • 前端面试之路二(javaScript基础整理)

    摘要:在标签中添加属性,本质上是跟在标签里面写属性时一样的,所以属性值最终都会编译为字符串类型。这个节点包括很多,比如,以及一些方法等方法。一个对象有很多,该集合名字为,里面有其他以及,里面有很多。 一、变量类型和计算 JS中使用typeof能得到哪些类型 变量类型 值类型:变量本身就是含有赋予给它的数值的,它的变量本身及保存的数据都存储在栈的内存块当中 引用类型:引用类型当然是分配到...

    AbnerMing 评论0 收藏0
  • 深究JavaScript——参数传递与变量复制

    摘要:在操作对象时,实际上是在操作对象的引用而不是实际的对象。任一变量值操作互不影响。访问变量有按值和按引用两种方式,而参数只能按值传递。基本类型参数传递传给函数的是数值的一个复制,函数中对其的修改外部不可见。    ECMAScript 变量可能包含两种不同数据类型的值:基本类型值和引用类型值。 基本类型值指的是简单的数据段,而引用类型值指那些可能由多个值构成的对象。   5 种基本数据类...

    jzman 评论0 收藏0

发表评论

0条评论

Dionysus_go

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<