gpt4 book ai didi

javascript - javaScript中的词法作用域/闭包

转载 作者:数据小太阳 更新时间:2023-10-29 04:21:52 25 4
gpt4 key购买 nike

我了解“js”中的函数具有词法范围(即函数在定义时创建其环境(范围),而不是在执行时创建。)

function f1() {
var a = 1;
f2();
}

function f2() {
return a;
}
f1(); // a is not defined

当我只运行“f()”时,它会返回内部函数。我明白了,这就是'return'的作用!
function f() {
var b = "barb";
return function() {
return b;
}
}
console.log(b); //ReferenceError: b is not defined

为什么会出现“ReferenceError:b 未定义?”
但是上面的内部函数不能访问它的空间、f() 的空间等。因为'b' 被返回到全局空间,console.log() 不会工作吗?

但是,当我将 'f()' 分配给一个新变量并运行它时:
 var x = f(); 
x();// "barb"
console.log(b); //ReferenceError: b is not defined

这将返回“b”,即“barb”,但是当您再次运行 console.log() 时,您将得到 'ReferenceError: 'b' is not defined';自从它被返回后,'b' 现在不是在全局范围内了吗?那么为什么 'x()' 不像 'f()' 一样返回内部函数呢?

最佳答案

你,我的 friend ,完全糊涂了。您的第一句话本身就是错误的:

functions create their environment (scope) when they are defined not when they are executed


其实恰恰相反。定义函数不会创建范围。调用函数会创建一个作用域。
什么是范围?
简单来说,作用域就是变量的生命周期。你看,每一个变量都是诞生、生和死的。作用域的开始标志着变量的诞生时间,作用域的结束标志着它死亡的时间。
一开始只有一个范围(称为程序范围或全局范围)。在这个范围内创建的变量只有在程序结束时才会消失。它们被称为全局变量。
例如,考虑这个程序:

const x = 10;       // global variable x

{ // beginning of a scope
const x = 20; // local variable x
console.log(x); // 20
} // end of the scope

console.log(x); // 10

这里我们创建了一个名为 x 的全局变量。 .然后我们创建了一个 block 作用域。在这个 block 作用域内,我们创建了一个局部变量 x .因为当我们记录时局部变量会影响全局变量 x我们得到 20 .当我们登录 x 时回到全局范围我们得到 10 (本地 x 现在已经死了)。
block 作用域和函数作用域
现在编程中有两种主要的作用域类型—— block 作用域和函数作用域。
上一个示例中的作用域是 block 作用域。这只是一段代码。由此得名。 block 作用域立即执行。
另一方面,函数作用域是 block 作用域的模板。顾名思义,函数作用域属于函数。但是,更准确地说,它属于函数调用。在调用函数之前,函数作用域不存在。例如:

const x = 10;

function inc(x) {
console.log(x + 1);
}

inc(3); // 4
console.log(x); // 10
inc(7); // 8

正如您所看到的,每次调用函数时都会创建一个新范围。这就是你得到输出的原因 4 , 108 .
最初,JavaScript 只有函数作用域。它没有 block 作用域。因此,如果你想创建一个 block 作用域,那么你必须创建一个函数并立即执行它:

const x = 10;         // global variable x

(function () { // beginning of a scope
const x = 20; // local variable x
console.log(x); // 20
}()); // end of the scope

console.log(x); // 10

这种模式称为 immediately invoked function expression (IIFE) .当然,现在我们可以使用 const 创建 block 范围的变量。和 let .
词法作用域和动态作用域
函数作用域又可以有两种类型——词法作用域和动态作用域。你看,在一个函数中有两种类型的变量:
  • 自由变量
  • 绑定(bind)变量

  • 在范围内声明的变量绑定(bind)到该范围。未在作用域内声明的变量是免费的。这些自由变量属于其他范围,但属于哪个范围?
    词法作用域
    在词法作用域中,自由变量必须属于父作用域。例如:

    function add(x) {         // template of a new scope, x is bound in this scope
    return function (y) { // template of a new scope, x is free, y is bound
    return x + y; // x resolves to the parent scope
    };
    }

    const add10 = add(10); // create a new scope for x and return a function
    console.log(add10(20)); // create a new scope for y and return x + y

    与大多数编程语言一样,JavaScript 具有词法作用域。
    动态范围
    与词法作用域相反,在动态作用域中,自由变量必须属于调用作用域(调用函数的作用域)。例如(这也不是 JS - 它没有动态范围):
    function add(y) {   // template of a new scope, y is bound, x is free
    return x + y; // x resolves to the calling scope
    }

    function add10(y) { // template of a new scope, bind y
    var x = 10; // bind x
    return add(y); // add x and y
    }

    print(add10(20)); // calling add10 creates a new scope (the calling scope)
    // the x in add resolves to 10 because the x in add10 is 10
    而已。简单吧?
    问题
    您的第一个程序的问题是 JavaScript 没有动态范围。它只有词法作用域。看到错误了吗?

    function f1() {
    var a = 1;
    f2();
    }

    function f2() {
    return a;
    }

    f1(); // a is not defined (obviously - f2 can't access the `a` inside f1)

    您的第二个程序非常困惑:

    function f() {
    var b = "barb";

    return function() {
    return b;
    }
    }

    console.log(b); //ReferenceError: b is not defined

    以下是错误:
  • 你从来没有打过f .因此变量 b永远不会被创建。
  • 即使你调用 f变量 b将是 f 本地的.

  • 这是你需要做的:

    function f() {
    const b = "barb";

    return function() {
    return b;
    }
    }

    const x = f();

    console.log(x());

    当您调用 x它返回 b .然而,这并不能使 b全局的。制作 b全局你需要这样做:

    function f() {
    const b = "barb";

    return function() {
    return b;
    }
    }

    const x = f();
    const b = x();
    console.log(b);

    希望这有助于您了解范围和功能。

    关于javascript - javaScript中的词法作用域/闭包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17279437/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com