设计师每天都上的网站,学校电脑课做网站的软件,广州营销课程培训班,公司网站域名如何申请文章目录 一、是什么二、使用场景柯里化函数使用闭包模拟私有方法其他 三、注意事项 一、是什么
一个函数和对其周围状态#xff08;lexical environment#xff0c;词法环境#xff09;的引用捆绑在一起#xff08;或者说函数被引用包围#xff09;#xff0c;这样的组… 文章目录 一、是什么二、使用场景柯里化函数使用闭包模拟私有方法其他 三、注意事项 一、是什么
一个函数和对其周围状态lexical environment词法环境的引用捆绑在一起或者说函数被引用包围这样的组合就是闭包closure
也就是说闭包让你可以在一个内层函数中访问到其外层函数的作用域
在 JavaScript中每当创建一个函数闭包就会在函数创建的同时被创建出来作为函数内部与外部连接起来的一座桥梁
下面给出一个简单的例子
function init() {var name Mozilla; // name 是一个被 init 创建的局部变量function displayName() { // displayName() 是内部函数一个闭包alert(name); // 使用了父函数中声明的变量}displayName();
}
init();displayName() 没有自己的局部变量。然而由于闭包的特性它可以访问到外部函数的变量
二、使用场景
任何闭包的使用场景都离不开这两点
创建私有变量延长变量的生命周期 一般函数的词法环境在函数返回后就被销毁但是闭包会保存对创建时所在词法环境的引用即便创建时所在的执行上下文被销毁但创建时所在词法环境依然存在以达到延长变量的生命周期的目的 下面举个例子
在页面上添加一些可以调整字号的按钮
function makeSizer(size) {return function() {document.body.style.fontSize size px;};
}var size12 makeSizer(12);
var size14 makeSizer(14);
var size16 makeSizer(16);document.getElementById(size-12).onclick size12;
document.getElementById(size-14).onclick size14;
document.getElementById(size-16).onclick size16;柯里化函数
柯里化的目的在于避免频繁调用具有相同参数函数的同时又能够轻松的重用
// 假设我们有一个求长方形面积的函数
function getArea(width, height) {return width * height
}
// 如果我们碰到的长方形的宽老是10
const area1 getArea(10, 20)
const area2 getArea(10, 30)
const area3 getArea(10, 40)// 我们可以使用闭包柯里化这个计算面积的函数
function getArea(width) {return height {return width * height}
}const getTenWidthArea getArea(10)
// 之后碰到宽度为10的长方形就可以这样计算面积
const area1 getTenWidthArea(20)// 而且如果遇到宽度偶尔变化也可以轻松复用
const getTwentyWidthArea getArea(20)使用闭包模拟私有方法
在JavaScript中没有支持声明私有变量但我们可以使用闭包来模拟私有方法
下面举个例子
var Counter (function() {var privateCounter 0;function changeBy(val) {privateCounter val;}return {increment: function() {changeBy(1);},decrement: function() {changeBy(-1);},value: function() {return privateCounter;}}
})();var Counter1 makeCounter();
var Counter2 makeCounter();
console.log(Counter1.value()); /* logs 0 */
Counter1.increment();
Counter1.increment();
console.log(Counter1.value()); /* logs 2 */
Counter1.decrement();
console.log(Counter1.value()); /* logs 1 */
console.log(Counter2.value()); /* logs 0 */上述通过使用闭包来定义公共函数并令其可以访问私有函数和变量这种方式也叫模块方式
两个计数器 Counter1 和 Counter2 是维护它们各自的独立性的每次调用其中一个计数器时通过改变这个变量的值会改变这个闭包的词法环境不会影响另一个闭包中的变量
其他
例如计数器、延迟调用、回调等闭包的应用其核心思想还是创建私有变量和延长变量的生命周期
三、注意事项
如果不是某些特定任务需要使用闭包在其它函数中创建函数是不明智的因为闭包在处理速度和内存消耗方面对脚本性能具有负面影响
例如在创建新的对象或者类时方法通常应该关联于对象的原型而不是定义到对象的构造器中。
原因在于每个对象的创建方法都会被重新赋值
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;
};
MyObject.prototype.getMessage function() {return this.message;
};