函数
JavaScript 中的函数是一种可重复使用的代码块,它接受输入(参数),并在执行完特定任务后返回一个值。函数在 JavaScript 中是一等公民,这意味着它们可以被存储在变量中,传递给其他函数作为参数,以及从其他函数中返回。
- 函数作用域:JavaScript 中的函数具有自己的作用域,这意味着函数内部声明的变量在外部是不可见的,除非它们被显式地返回或暴露出来。
- 闭包:函数和其周围的词法环境的组合形成了闭包。闭包可以访问定义它们的外部函数中的变量,即使在外部函数执行完毕后依然可以访问。
- 递归:函数可以调用自身,这种技术称为递归。递归在解决特定问题时非常有用,比如树结构的遍历、阶乘计算等。
- 高阶函数:函数可以接受函数作为参数,或者返回一个函数,这种函数被称为高阶函数。高阶函数在函数式编程中扮演着重要角色。
闭包
闭包(Closure)是指在某个作用域内部定义的函数,能够访问该作用域中的变量,并且能够在其定义的外部作用域中被调用。换句话说,闭包可以“记住”并访问其创建时所处的作用域中的变量,即使这个作用域已经不存在了。
闭包通常由两个部分组成:
- 函数本身
- 函数所在的词法环境(Lexical Environment)
- 词法环境包含了函数定义时所处的作用域链以及在该作用域链上找到的所有变量。
function outer() {
var outerVar = 'outer';
function inner() {
console.log(outerVar); // 内部函数访问外部函数变量
}
return inner;
}
var innerFn = outer() // 调用外部函数, innerFn 成为内部函数的引用
innerFn() // 输出: 'outer'
inner 是一个闭包,它能够访问 outer 中定义的 outerVar 变量,即使 outer 已经执行完毕并且 outerVar 在外部函数执行结束后仍然存在于内存中。这是因为 inner 保留了对其创建时所在词法环境的引用,使得它可以继续访问外部函数的变量。
闭包重要应用场景:
- 封装私有变量和方法:使用闭包可以创建私有作用域,从而隐藏变量和方法,只暴露需要对外部可见的接口。
function createCounter() {
var count = 0;
return {
increment: function() {
count++;
console.log('Current count:', count);
},
reset: function() {
count = 0;
console.log('Counter reset.');
}
};
}
var counter = createCounter();
counter.increment(); // 输出: "Current count: 1"
counter.increment(); // 输出: "Current count: 2"
counter.reset(); // 输出: "Counter reset."
- 模块化:使用闭包可以创建模块化的代码结构,将相关的变量和方法封装在一个作用域内部,避免全局命名空间的污染。
var module = (function() {
var privateVar = 'private';
function privateFn() {
console.log('private function')
}
return {
publicMethods() {
console.log('public function');
privateFn();
}
}
})()
- 函数柯里化:闭包可以用来创建柯里化函数,即将多参数的函数转换为一系列接受单个参数的函数。
function add(x) {
return function(y) {
return x + y;
};
}
var add5 = add(5);
console.log(add5(3)); // 输出: 8
console.log(add5(7)); // 输出: 12
- 事件处理:闭包可以用来保存事件处理函数中所需的状态信息,例如保存点击计数或者其他状态。
function createButton(message) {
var button = document.createElement('button');
button.textContent = message;
button.addEventListener('click', function() {
console.log('Button clicked:', message);
});
return button;
}
var button1 = createButton('Button 1');
var button2 = createButton('Button 2');
document.body.appendChild(button1);
document.body.appendChild(button2);
PS: 函数作用域、上下文等请参考 javascript 篇。