资讯专栏INFORMATION COLUMN

【JavaScript】【函数】闭包闭包!

he_xd / 649人阅读

摘要:要想保存在循环过程中每一个的值,需要在匿名函数外部再套用一个匿名函数,在这个匿名函数中定义另一个变量并且立即执行来保存的值。这时最内部的匿名函数访问的是的值,所以数组中个匿名函数的返回值就是。才是匿名函数功能执行的环境。

闭包,有人说它是一种设计理念,有人说所有的函数都是闭包。我不知道如何去定义它,我也不准备去定义它,定义它就是限制了对它的理解。

我们依赖光来看清世间万物,光却遮住了黑暗。如同你脚下的路,让你看不清前行的方向。

在这里写一点我对闭包的理解。理解闭包的关键在于:外部函数调用之后其变量对象本应该被销毁,但闭包的存在使我们仍然可以访问外部函数的变量对象。

function outer() {
    var a = 1;
    return function() {
        return a;
    };
}
var b = outer();
console.log(b()); //1
模块级作用域
(function(){
    var now = new Date();
    if (now.getMonth() == 0 && now.getDate() == 1) {
        alert("Happy new Year!");
    }
})();

这种方式常用来限制向全局作用域添加过多的变量和函数。

创建私有变量
(funcion() {
    var a = 1;
    setA = function(val){
        a = val;
    };
    getA = function(){
        return a;
    };
})();
console.log(a); //报错
console.log(getA()); //1
setA(2);
console.log(getA()); //2

也可以这样写:

function outer(){
    var a = 1;
    return {
        setA: function(val) {
            a = val;  
        },
        getA: function() {
            return a;
        }
    };
}
var closure = outer();
console.log(a); //报错
console.log(closure.getA()); //1
closure.setA(2);
console.log(closure.getA()); //2

第一个例子中,setAgetA都是全局变量,用于读写私有变量a。第二个例子中将这两个方法作为一个对象返回并赋给一个全局变量closure,这样当outer执行完毕后,这两个方法(匿名函数)连同外部函数中的变量对象(a)依然不会被销毁。

闭包用于创建具有私有变量的实例对象,参考通过闭包创建具有私有属性的实例对象

闭包只能取得包含函数中任何变量的最后一个值
function arrFunc() {
    var arr = [];
    for (var i=0; i<10; i++) {
        arr[i] = function() {
            return i;
        };
    }
    return arr;
}

arr数组中包含了10个匿名函数,每个匿名函数都能访问外部函数的变量i,那么i是多少呢?当arrFunc执行完毕后,其作用域被销毁,但它的变量对象仍保存在内存中,得以被匿名访问,这时i的值为10。要想保存在循环过程中每一个i的值,需要在匿名函数外部再套用一个匿名函数,在这个匿名函数中定义另一个变量并且立即执行来保存i的值。

function arrFunc() {
    var arr = [];
    for (var i=0; i<10; i++) {
        arr[i] = function(num) {
            return function() {
                return num;
            };
        }(i);
    }
    return arr;
}
console.log(arrFunc()[1]()); //1

这时最内部的匿名函数访问的是num的值,所以数组中10个匿名函数的返回值就是1-10。

闭包中的this
var name = "window";
var obj = {
    name: "object",
    getName: function() {
        return function() {
            return this.name;
        };
    }
};
console.log(obj.getName()()); //window

obj.getName()()实际上是在全局作用域中调用了匿名函数,this指向了window。这里要理解函数名与函数功能是分割开的,不要认为函数在哪里,其内部的this就指向哪里。window才是匿名函数功能执行的环境。要想使this指向外部函数的执行环境,可以这样改写:

var name = "window";
var obj = {
    name: "object",
    getName: function() {
        var that = this;
        return function() {
            return that.name;
        };
    }
};
console.log(obj.getName()()); //object

argumentsthis也有相同的问题。下面的情况也要注意:

var name = "window";
var obj = {
    name: "object",
    getName: function() {
        return this.name;
    }
};
obj.getName(); //object
(obj.getName = obj.getName)(); //window 非严格模式下

obj.getName();这时getName()是在对象obj的环境中执行的,所以this指向obj
(obj.getName = obj.getName)赋值语句返回的是等号右边的值,在全局作用域中返回,所以(obj.getName = obj.getName)();this指向全局。要把函数名和函数功能分割开来

内存泄漏

闭包会引用包含函数的整个变量对象,如果闭包的作用域链中保存着一个HTML元素,那么就意味着该元素无法被销毁。所以我们有必要在对这个元素操作完之后主动销毁。

function assignHandler() {
    var element = document.getElementById("someElement");
    var id = element.id;
    element.onclick = function() {
        alert(id);
    };
    element = null;
}
函数内部的定时器

当函数内部的定时器引用了外部函数的变量对象时,该变量对象不会被销毁。

(function() {
    var a = 0;
    setInterval(function(){
        console.log(a++);
    }, 1000);
})();
运用闭包的关键

闭包引用外部函数变量对象中的值;

在外部函数的外部调用闭包。

转载请注明出处:https://segmentfault.com/a/1190000004585904

文章不定期更新完善,如果能对你有一点点启发,我将不胜荣幸。

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

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

相关文章

  • Javascript闭包入门(译文)

    摘要:也许最好的理解是闭包总是在进入某个函数的时候被创建,而局部变量是被加入到这个闭包中。在函数内部的函数的内部声明函数是可以的可以获得不止一个层级的闭包。 前言 总括 :这篇文章使用有效的javascript代码向程序员们解释了闭包,大牛和功能型程序员请自行忽略。 译者 :文章写在2006年,可直到翻译的21小时之前作者还在完善这篇文章,在Stackoverflow的How do Java...

    Fourierr 评论0 收藏0
  • 理解Javascript闭包

    摘要:但是闭包也不是什么复杂到不可理解的东西,简而言之,闭包就是闭包就是函数的局部变量集合,只是这些局部变量在函数返回后会继续存在。可惜的是,并没有提供相关的成员和方法来访问闭包中的局部变量。 (收藏自 技术狂) 前言:还是一篇入门文章。Javascript中有几个非常重要的语言特性——对象、原型继承、闭包。其中闭包 对于那些使用传统静态语言C/C++的程序员来说是一个新的语言特性。本文将...

    dayday_up 评论0 收藏0
  • JavaScript闭包,只学这篇就够了

    摘要:当在中调用匿名函数时,它们用的都是同一个闭包,而且在这个闭包中使用了和的当前值的值为因为循环已经结束,的值为。最好将闭包当作是一个函数的入口创建的,而局部变量是被添加进这个闭包的。 闭包不是魔法 这篇文章使用一些简单的代码例子来解释JavaScript闭包的概念,即使新手也可以轻松参透闭包的含义。 其实只要理解了核心概念,闭包并不是那么的难于理解。但是,网上充斥了太多学术性的文章,对于...

    CoderBear 评论0 收藏0
  • 还担心面试官问闭包

    摘要:一言以蔽之,闭包,你就得掌握。当函数记住并访问所在的词法作用域,闭包就产生了。所以闭包才会得以实现。从技术上讲,这就是闭包。执行后,他的内部作用域并不会消失,函数依然保持有作用域的闭包。 网上总结闭包的文章已经烂大街了,不敢说笔者这篇文章多么多么xxx,只是个人理解总结。各位看官瞅瞅就好,大神还希望多多指正。此篇文章总结与《JavaScript忍者秘籍》 《你不知道的JavaScri...

    tinyq 评论0 收藏0
  • [学习笔记] JavaScript 闭包

    摘要:但是,必须强调,闭包是一个运行期概念。通过原型链可以实现继承,而与闭包相关的就是作用域链。常理来说,一个函数执行完毕,其执行环境的作用域链会被销毁。所以此时,的作用域链虽然销毁了,但是其活动对象仍在内存中。 学习Javascript闭包(Closure)javascript的闭包JavaScript 闭包深入理解(closure)理解 Javascript 的闭包JavaScript ...

    sunsmell 评论0 收藏0
  • JavaScript 闭包

    摘要:闭包的注意事项通常,函数的作用域及其所有变量都会在函数执行结束后被销毁。但是,在创建了一个闭包以后,这个函数的作用域就会一直保存到闭包不存在为止。最后通过释放了和对闭包的引用。从而使用闭包模块化代码,减少全局变量的污染。 JavaScript 闭包 原文链接 什么是闭包(Closure) 简单讲,闭包就是指有权访问另一个函数作用域中的变量的函数。 MDN 上面这么说:闭包是一种特殊的...

    zhou_you 评论0 收藏0

发表评论

0条评论

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