返回

红宝书阅读笔记:函数(3)

前端

正文

1. arguments.callee

arguments.callee 是一个指向正在执行函数的指针。这允许您从函数内部调用自身,从而实现递归或创建闭包。例如,编写阶乘函数时,可以使用 return num * arguments.callee(num-1) 的表达式。

function factorial(num) {
  if (num === 0) {
    return 1;
  } else {
    return num * arguments.callee(num-1);
  }
}

console.log(factorial(5)); // 输出: 120

注意: 在严格模式下访问 arguments.callee 会出错。此时,可以使用命名函数表达式来达到相同目的。

const factorial = function(num) {
  if (num === 0) {
    return 1;
  } else {
    return num * factorial(num-1);
  }
};

console.log(factorial(5)); // 输出: 120

2. 闭包

闭包是指引用了另一个函数作用域中变量的函数。当一个函数被另一个函数调用时,它将创建一个新的词法环境,并将父函数的词法环境存储在内部。这允许内部函数访问父函数的作用域,即使父函数已经执行完毕。

闭包常用于创建私有变量、实现模块化和封装。

function createCounter() {
  let count = 0;

  return function() {
    return count++;
  };
}

const counter1 = createCounter();
const counter2 = createCounter();

console.log(counter1()); // 输出: 0
console.log(counter1()); // 输出: 1
console.log(counter2()); // 输出: 0

在这个例子中,createCounter 函数创建了一个闭包,其中包含一个私有变量 countcounter1counter2 都是 createCounter 函数的实例,它们都引用了相同的闭包,因此它们都可以访问 count 变量。

3. 作用域

作用域是函数或代码块可以访问的变量和函数的集合。JavaScript 具有两种主要的作用域:

  • 全局作用域: 这是脚本中所有代码都可以访问的作用域。全局变量在全局作用域中声明。
  • 局部作用域: 这是函数或代码块内部的作用域。局部变量在局部作用域中声明。

局部变量只能在声明它们的函数或代码块内部访问。全局变量可以在任何地方访问。

let globalVariable = 10;

function myFunction() {
  let localVariable = 20;

  console.log(globalVariable); // 输出: 10
  console.log(localVariable); // 输出: 20
}

myFunction();

console.log(globalVariable); // 输出: 10
console.log(localVariable); // 输出: ReferenceError: localVariable is not defined

4. 词法环境

词法环境是一个函数或代码块可以访问的变量和函数的集合,包括该函数或代码块内部声明的变量和函数,以及父函数或代码块的词法环境。

词法环境决定了函数或代码块可以访问哪些变量和函数。词法环境在函数或代码块创建时确定,并在其执行期间保持不变。

function createCounter() {
  let count = 0;

  return function() {
    return count++;
  };
}

const counter1 = createCounter();
const counter2 = createCounter();

console.log(counter1()); // 输出: 0
console.log(counter1()); // 输出: 1
console.log(counter2()); // 输出: 0

在这个例子中,createCounter 函数创建了一个闭包,其中包含一个私有变量 countcounter1counter2 都是 createCounter 函数的实例,它们都引用了相同的闭包,因此它们都可以访问 count 变量。

词法环境决定了 counter1counter2 可以访问哪些变量和函数。在 createCounter 函数内部创建的 count 变量在闭包中是私有的,因此 counter1counter2 不能直接访问它。但是,count 变量可以通过闭包中返回的函数访问。

5. this

this 是指函数执行时的上下文对象。它可以是全局对象、函数对象或其他对象。

this 的值由函数的调用方式决定。在以下情况下,this 的值为全局对象:

  • 函数在全局作用域中调用
  • 函数作为回调函数被调用
  • 函数使用 bind()call()apply() 方法调用

在以下情况下,this 的值为函数对象:

  • 函数作为构造函数被调用

在以下情况下,this 的值为其他对象:

  • 函数作为该对象的方法被调用
function myFunction() {
  console.log(this);
}

myFunction(); // 输出: Window { ... }

const object = {
  myFunction: function() {
    console.log(this);
  }
};

object.myFunction(); // 输出: { myFunction: [Function: myFunction] }

总结

本文探讨了函数(3)的知识点,包括 arguments.callee、闭包、作用域、词法环境和 this 的概念和用法。通过提供清晰易懂的示例代码和案例解析,帮助读者全面掌握函数的奥秘。