细数《JavaScript高级程序设计》中的函数机制
2023-09-27 02:56:32
《JavaScript高级程序设计》(第三版)学习复盘(二)
在上一篇文章中,我们对《JavaScript高级程序设计》(第三版)中的变量进行了深入探讨。在这篇文章中,我们将把目光转向函数。函数是JavaScript编程的基石,也是理解JavaScript程序执行流程的关键。
函数声明提升
函数声明提升是一个非常重要的概念,它意味着函数声明在代码执行之前就被解释器读取和执行。这意味着函数可以在其声明之前被调用,而不会报错。
foo();
function foo() {
console.log('Hello, world!');
}
这段代码首先调用了foo()函数,然后才定义了foo()函数。然而,代码不会报错,因为在执行foo()函数之前,函数声明就被提升了。
递归函数
递归函数是在一个函数通过名字调用自身的情况下构成的。递归函数可以用来解决许多问题,比如阶乘计算、斐波那契数列计算等等。
function factorial(n) {
if (n === 0) {
return 1;
} else {
return n * factorial(n - 1);
}
}
这个函数计算n的阶乘。它使用递归来减少问题的大小,直到达到基本情况(n === 0)。
闭包
闭包是指有权访问另一个函数作用域中的变量的函数。闭包可以在函数内部访问父函数的作用域,即使父函数已经执行完毕。
function outer() {
var a = 1;
function inner() {
console.log(a);
}
return inner;
}
var innerFunc = outer();
innerFunc(); // 1
在这个例子中,inner()函数是一个闭包,它可以访问outer()函数的作用域,即使outer()函数已经执行完毕。
作用域链
作用域链是一个函数可以访问的变量的作用域的列表。作用域链从当前函数的作用域开始,然后是父函数的作用域,依此类推。
function outer() {
var a = 1;
function inner() {
var b = 2;
console.log(a); // 1
console.log(b); // 2
}
inner();
}
outer();
在这个例子中,inner()函数的作用域链包括inner()函数的作用域和outer()函数的作用域。inner()函数可以访问a和b这两个变量,因为它们都在inner()函数的作用域链中。
this
this指向当前函数的作用域。this的值取决于函数的调用方式。
function outer() {
var a = 1;
function inner() {
console.log(this.a);
}
inner(); // undefined
inner.call(this); // 1
}
outer();
在这个例子中,inner()函数被调用了两次。第一次调用时,this指向全局对象,因此console.log(this.a)输出undefined。第二次调用时,inner()函数被显式地调用,this指向outer()函数的作用域,因此console.log(this.a)输出1。
call、apply和bind
call、apply和bind都是可以改变函数this指向的函数。
- call()方法接受两个参数:第一个参数是要改变this指向的对象,第二个参数是要传递给函数的参数列表。
- apply()方法也接受两个参数:第一个参数是要改变this指向的对象,第二个参数是要传递给函数的参数数组。
- bind()方法也接受两个参数:第一个参数是要改变this指向的对象,第二个参数是要传递给函数的参数列表。与call()和apply()不同的是,bind()方法返回一个新的函数,该函数的this指向已经被改变。
function outer() {
var a = 1;
function inner() {
console.log(this.a);
}
inner.call(this); // 1
inner.apply(this); // 1
var boundInner = inner.bind(this);
boundInner(); // 1
}
outer();
在这个例子中,inner()函数被调用了三次。第一次调用时,inner()函数被显式地调用,this指向outer()函数的作用域,因此console.log(this.a)输出1。第二次调用时,inner()函数被apply()方法调用,this指向outer()函数的作用域,因此console.log(this.a)输出1。第三次调用时,inner()函数被bind()方法调用,this指向outer()函数的作用域,因此console.log(this.a)输出1。