JS闭包原理
什么是必包
有权访问另一个函数作用域中的变量的函数;一般情况就是在一个函数中包含另一个函数。
好像必包挺简单的,但是注意必包是有超能力的
慢慢品味“有权访问另一个函数作用域中的变量”,那要是没有必包是不是就不能访问函数作用域中的变量了呢,终于意识到了吧。函数作用域是独立的、封闭的,外部的执行环境是访问不了的,但是闭包具有这个能力和权限。
function person () {
var fruit = "鱼"
function say () {
console.log("我想吃" + fruit)
}
say()
}
var personSay = person();
console.log(personSay()) // 我想吃鱼
console.log(personSay()) // 我想吃鱼
console.log(personSay()) // 我想吃鱼
性能考量
如果不是特殊情况要求使用必包,否则必包必须少用,因为使用必包会造成额外的资源和性能损耗。
例如:创建新的对象或者类时,方法通常关联与对象的原型,而不是定义到对象的构造器中。原因是这将导致每次构造器被调用时,方法都会被重新赋值一次(也就是说,对于每个对象的创建,方法都会被重新赋值)
考虑以下例子
function MyObject(name, message) {
this.name = name.toString();
this.message = message.toString();
this.getName = function() {
return this.name;
};
this.getMessage = function() {
return this.message;
};
}
在上面的代码中,我们并没有利用到闭包的好处,因此可以避免使用闭包。修改成如下:
function MyObject(name, message) {
this.name = name.toString();
this.message = message.toString();
}
MyObject.prototype = {
getName: function() {
return this.name;
},
getMessage: function() {
return this.message;
}
};
但我们不建议重新定义原型(应避免,因为有可能会把原型上的其它属性/方法给删了)。可改成如下例子:
function MyObject(name, message) {
this.name = name.toString();
this.message = message.toString();
}
MyObject.prototype.getName = function() {
return this.name;
};
MyObject.prototype.getMessage = function() {
return this.message;
};