JavaScript 中的词法作用域
Lexical Scope in JavaScript
我对作用域在 JavaScript 中的确切工作方式感到有些困惑,主要是词法作用域。我知道全局范围内的变量在任何地方都可以访问,在 JavaScript 中创建新范围的唯一方法是通过创建函数(或在 ES6 中使用 let )。但是,我不太明白什么是词法作用域is/means。我在整个互联网上都看过,找不到明确的解释。
我觉得我有点开始理解它了,但让我向您确认一下 JavaScript 那里的向导以确保我是正确的。
因此,根据我的理解,词法作用域意味着静态作用域,例如,函数的作用域不是由调用它的位置创建的,而是由创建函数本身的位置创建的。下面的代码演示了这个概念:
var x = "global";
function foo() {
console.log(x);
}
function bar() {
var x = "bar";
foo();
}
function baz() {
var x = "baz";
foo();
}
bar();
baz();
打印到控制台的是"global"两次。这是因为当函数 foo 被调用时,解释器首先检查 foo 的范围以查看它是否有变量 "x" 然后检查全局范围,而不是 bar 或 baz 范围。变量 "x" 不是从调用函数 foo 的地方获取的,而是从它创建的地方获取的,因此是词法范围的。我是对的,这有意义吗?
词法作用域的另一个例子是闭包,对吧?因此,例如,内部函数可以访问外部函数的变量,无论内部函数在哪里被调用,因为词法范围,对吗?
最后,我的最后一个例子是箭头函数。它们允许 "this" 的词法范围,对吗?所以,例如,
var obj = {
name: "Rob",
print() {
setTimeout(() => {
console.log(this.name)
}, 1000);
}
};
如果它是一个标准的内联函数,"this" 不会绑定到全局对象,"this" 会绑定到 obj,因为 "this" 的词法作用域带有箭头函数。
我说的都对吗?另外,有人能给我一个词法范围的明确定义吗? JavaScript 中还有其他我应该知道的词法范围示例吗?
谢谢。
当您查看程序的某些源代码时,您正在查看其词法结构。当程序实际运行时,执行可以跳来跳去,对事物的评估可以 change.This 是所有开始有意义的部分。
您可能希望将其视为功能词法作用域和块词法作用域。至于其他的,你似乎已经掌握了它的想法。
"global" 被打印了两次,因为 "foo" 是一个 闭包 ,它已将 "x" 的全局范围添加到其内存中,这就是我的学习方式是,闭包是记住
的函数
你对标准函数(包括闭包内的闭包)作用域的理解是正确的,但对于箭头函数,这个说法是错误的:
"this" is bound to obj because of the lexical scoping of "this" with arrow functions.
函数内的箭头函数 this
与创建时函数外的任何 this
相同。在您的示例中,它未绑定到 obj
,而是绑定到已绑定到正在创建 obj
的位置。
它在以下情况下很有用:
this.values.filter( x => x < this.max );
箭头函数内部 this
与函数外部相同。对于常规函数,它可能是这样写的:
this.values.filter( function ( x ) { return x < this.max }.bind( this ) );
或:
var self = this;
this.values.filter( function ( x ) { return x < self.max } );
要了解词法作用域,您需要对作用域有一个基本的了解。在javascript中,我们将作用域分为三种
- 函数范围
- 块范围
- 词法作用域
Function Scope -> 函数内部定义的变量在函数中被考虑 scope.the var 关键字用于定义函数范围内的变量。
块范围 -> 在 if、switch 条件、for 和 while 循环中的区域中定义的变量。
每当您看到“{}”花括号时,它就是一个块。在 Es6 中,const 和 let 关键字允许开发人员在块范围内声明变量。这意味着这些变量仅存在于相应的块中。
function animal(){
if(true){
var animal1 = "cat";
const animal2 = "dog";
let animal3 = "rat";
}
console.log(animal1);
console,log(animal2); //animal2 is not defiend
console,log(animal3); //animal3 is not defiend
}
animal();
结果
猫
未定义 animal2
未定义 animal3
词法作用域-> 在第 1 行我想说 "children scope have access to the variable in parent scope"
`
var outerFunction = function()
{
if(true){
var x = 5;
const y = 10;
}
var innerFunction = function(){
if(true){
alert(x);
//alert(y); //y is not defiend on line 13
}
}
innerFunction();
}
outerFunction();
//console.log(x); // x is not defiend on line 20
`。
变量的范围由它们在源代码中的位置定义。
为了解析变量 javascript 从最里面的作用域开始向外搜索,直到找到它要查找的变量。
词法范围很好,因为我们可以通过查看代码轻松地找出变量的值;而在动态作用域中,变量的含义可以在运行时通过使其变得更加困难来改变
我对作用域在 JavaScript 中的确切工作方式感到有些困惑,主要是词法作用域。我知道全局范围内的变量在任何地方都可以访问,在 JavaScript 中创建新范围的唯一方法是通过创建函数(或在 ES6 中使用 let )。但是,我不太明白什么是词法作用域is/means。我在整个互联网上都看过,找不到明确的解释。
我觉得我有点开始理解它了,但让我向您确认一下 JavaScript 那里的向导以确保我是正确的。
因此,根据我的理解,词法作用域意味着静态作用域,例如,函数的作用域不是由调用它的位置创建的,而是由创建函数本身的位置创建的。下面的代码演示了这个概念:
var x = "global";
function foo() {
console.log(x);
}
function bar() {
var x = "bar";
foo();
}
function baz() {
var x = "baz";
foo();
}
bar();
baz();
打印到控制台的是"global"两次。这是因为当函数 foo 被调用时,解释器首先检查 foo 的范围以查看它是否有变量 "x" 然后检查全局范围,而不是 bar 或 baz 范围。变量 "x" 不是从调用函数 foo 的地方获取的,而是从它创建的地方获取的,因此是词法范围的。我是对的,这有意义吗?
词法作用域的另一个例子是闭包,对吧?因此,例如,内部函数可以访问外部函数的变量,无论内部函数在哪里被调用,因为词法范围,对吗?
最后,我的最后一个例子是箭头函数。它们允许 "this" 的词法范围,对吗?所以,例如,
var obj = {
name: "Rob",
print() {
setTimeout(() => {
console.log(this.name)
}, 1000);
}
};
如果它是一个标准的内联函数,"this" 不会绑定到全局对象,"this" 会绑定到 obj,因为 "this" 的词法作用域带有箭头函数。
我说的都对吗?另外,有人能给我一个词法范围的明确定义吗? JavaScript 中还有其他我应该知道的词法范围示例吗?
谢谢。
当您查看程序的某些源代码时,您正在查看其词法结构。当程序实际运行时,执行可以跳来跳去,对事物的评估可以 change.This 是所有开始有意义的部分。
您可能希望将其视为功能词法作用域和块词法作用域。至于其他的,你似乎已经掌握了它的想法。
"global" 被打印了两次,因为 "foo" 是一个 闭包 ,它已将 "x" 的全局范围添加到其内存中,这就是我的学习方式是,闭包是记住
的函数你对标准函数(包括闭包内的闭包)作用域的理解是正确的,但对于箭头函数,这个说法是错误的:
"this" is bound to obj because of the lexical scoping of "this" with arrow functions.
函数内的箭头函数 this
与创建时函数外的任何 this
相同。在您的示例中,它未绑定到 obj
,而是绑定到已绑定到正在创建 obj
的位置。
它在以下情况下很有用:
this.values.filter( x => x < this.max );
箭头函数内部 this
与函数外部相同。对于常规函数,它可能是这样写的:
this.values.filter( function ( x ) { return x < this.max }.bind( this ) );
或:
var self = this;
this.values.filter( function ( x ) { return x < self.max } );
要了解词法作用域,您需要对作用域有一个基本的了解。在javascript中,我们将作用域分为三种
- 函数范围
- 块范围
- 词法作用域
Function Scope -> 函数内部定义的变量在函数中被考虑 scope.the var 关键字用于定义函数范围内的变量。
块范围 -> 在 if、switch 条件、for 和 while 循环中的区域中定义的变量。 每当您看到“{}”花括号时,它就是一个块。在 Es6 中,const 和 let 关键字允许开发人员在块范围内声明变量。这意味着这些变量仅存在于相应的块中。
function animal(){
if(true){
var animal1 = "cat";
const animal2 = "dog";
let animal3 = "rat";
}
console.log(animal1);
console,log(animal2); //animal2 is not defiend
console,log(animal3); //animal3 is not defiend
}
animal();
结果
猫
未定义 animal2
未定义 animal3
词法作用域-> 在第 1 行我想说 "children scope have access to the variable in parent scope" `
var outerFunction = function()
{
if(true){
var x = 5;
const y = 10;
}
var innerFunction = function(){
if(true){
alert(x);
//alert(y); //y is not defiend on line 13
}
}
innerFunction();
}
outerFunction();
//console.log(x); // x is not defiend on line 20
`。 变量的范围由它们在源代码中的位置定义。 为了解析变量 javascript 从最里面的作用域开始向外搜索,直到找到它要查找的变量。 词法范围很好,因为我们可以通过查看代码轻松地找出变量的值;而在动态作用域中,变量的含义可以在运行时通过使其变得更加困难来改变