前端基础笔记

【javascript】闭包

2017-11-20  本文已影响2人  shanruopeng

闭包

function createComparisonFunction(propertyName) {
    return function(object1, object2){
    //内部函数的作用域链中包含createComparisonFunction()的作用域
        var value1 = object1[propertyName];
        var value2 = object2[propertyName];
        if (value1 < value2){
            return -1;
        } else if (value1 > value2){
            return 1;
        } else {
            return 0;
        }
    };
}
//创建函数
var compareNames = createComparisonFunction("name");
//调用函数
var result = compareNames({ name: "Nicholas" }, { name: "Greg" });
//解除对匿名函数的引用(以便释放内存)
compareNames = null;

闭包与变量

function createFunctions(){
    var result = new Array();
    for (var i=0; i < 10; i++){
        result[i] = function(){
            return i;
        };
    }
    return result;
}
//这个函数会返回一个函数数组,每个函数都返回10
/**因为每个函数的作用域链中都保存着createFunctions()函数的活动对象,所以它们引用的都是同一个变量i 。当createFunctions()函数返回后,变量i的值是10,此时每个函数都引用着保存变量i 的同一个变量对象,所以在每个函数内部i 的值都是10**/
function createFunctions(){
    var result = new Array();
    for (var i=0; i < 10; i++){
        result[i] = function(num){
            //创建并返回了一个访问num 的闭包
            return function(){
                return num;
            };
        }(i);//将立即执行改匿名函数的结果赋给数组
    }
    return result;
}

关于this对象

var name = "The Window";
var object = {
    name : "My Object",
    getNameFunc : function(){
        return function(){
            return this.name;
        };
    }
};
alert(object.getNameFunc()()); //"The Window"(在非严格模式下)
var name = "The Window";
var object = {
    name : "My Object",
    getNameFunc : function(){
        var that = this;
        return function(){
            return that.name;
        };
    }
};
alert(object.getNameFunc()()); //"My Object"
/**在定义匿名函数之前,我们把this对象赋值给了一个名叫that的变量。而在定义了闭包之后,闭包也可以访问这个变量,因为它是我们在包含函数中特意声名的一个变量。即使在函数返回之后,that 也仍然引用着object,所以调用object.getNameFunc()()就返回了"My Object"。**/

内存泄露

function assignHandler(){
    var element = document.getElementById("someElement");
    element.onclick = function(){
        alert(element.id);
    };
}
/**由于匿名函数保存了一个对assignHandler()的活动对象的引用,因此就会导致无法减少element 的引用数。只要匿名函数存在,element的引用数至少也是1,因此它所占用的内存就永远不会被回收**/
function assignHandler(){
    var element = document.getElementById("someElement");
    var id = element.id;
    element.onclick = function(){
        alert(id);
    };
    element = null;
}

模仿块级作用域

function outputNumbers(count){
    for (var i=0; i < count; i++){
        alert(i);
    }
    alert(i); //计数
}
//即使像下面这样错误地重新声明同一个变量,也不会改变它的值。
function outputNumbers(count){
    for (var i=0; i < count; i++){
        alert(i);
    }
    var i; //重新声明变量
    alert(i); //计数
}
//用作块级作用域(通常称为私有作用域)的匿名函数的语法
(function(){
//这里是块级作用域
})();
(function(){
    var now = new Date();
    if (now.getMonth() == 0 && now.getDate() == 1){
        alert("Happy new year!");
    }
})();

/**这种做法可以减少闭包占用的内存问题,因为没有指向匿名函数的引用。只要函
数执行完毕,就可以立即销毁其作用域链了。**/
好好学习
上一篇下一篇

猜你喜欢

热点阅读