JavaScript闭包详解
什么是闭包
闭包是指在一个函数内部定义的函数可以访问该函数的上下文环境中的变量和函数,即使在函数外部访问该函数的上下文环境也是无法访问到的。
举个例子:
function outer() {
var name = "张三";
function inner() {
console.log(name); // 可以访问外部函数中定义的变量
}
return inner;
}
var innerFun = outer();
innerFun(); // "张三"
在这个例子中,函数inner()
嵌套在另一个函数outer()
内部,它可以访问outer()
函数中定义的变量name
。在outer()
函数中,返回内层函数inner()
的引用,这就形成了一个闭包。
闭包的应用场景
闭包的应用有很多,其中最常见的是在封装对象的时候,使对象的部分属性或方法对外部不可访问。
封装变量
在JavaScript中,没有真正的私有变量。但是,如果我们定义一个函数并立即执行它,那么内部变量就会被封装,并且只能通过返回的函数才能访问到它们。这种方法被称为模块模式。
示例代码如下:
var obj = (function() {
var name = "张三";
var age = 18;
function getName() {
return name;
}
function getAge() {
return age;
}
return {
getName: getName,
getAge: getAge
}
})();
console.log(obj.getName()); // "张三"
console.log(obj.getAge()); // 18
在这个例子中,我们定义了一个立即执行的匿名函数,并返回一个包含getName()
和getAge()
方法的对象。这些方法内部访问了闭包中的name和age变量,但是从外部无法访问。
记忆化函数
记忆化是一个非常有用的技巧,可以根据函数的输入缓存运算结果,以避免重复计算。下面是一个例子,计算斐波那契数列中的第n项。
function fibonacci(n) {
if (n === 1 || n === 2) {
return 1;
}
return fibonacci(n - 1) + fibonacci(n - 2);
}
如果我们计算fibonacci(40),那么这个函数就会被调用1346269次,导致程序非常慢。考虑使用记忆化技巧。
function fibonacci(n) {
var cache = {};
function inner(num) {
if (num === 1 || num === 2) {
return 1;
}
if (cache[num]) {
return cache[num]; // 从缓存中返回结果
}
var result = inner(num - 1) + inner(num - 2);
cache[num] = result; // 缓存结果
return result;
}
return inner(n);
}
在这个例子中,我们定义了一个内部函数inner()
,它访问了一个闭包中的变量cache。cache
保存了已经计算过的结果,如果我们已经计算过结果,那么直接从cache
中返回结果即可。这个问题的计算复杂度被降低到了O(n),且即使是计算较大的斐波那契数列,也能非常快速地完成。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:JavaScript闭包详解 - Python技术站