宝哥软件园

通过函数范围和块级范围的javascript范围链

编辑:宝哥软件园 来源:互联网 时间:2021-08-30

在ES6之前,javascript只有全局作用域和函数作用域。范围是由变量定义的范围,可以访问。也就是说,如果在全局窗口上定义了一个变量,那么它可以在任何地方被访问,如果在函数内部定义了它,那么它只能在函数内部被访问。

只要页面没有关闭,全局作用域就会存在,而函数作用域只有在函数执行时才会存在,执行后会被破坏。每次执行一个函数,都会创建一个新的作用域。

那么什么是范围链呢?在理解范围链之前,我们首先理解运行时上下文的概念。

执行上下文:函数执行时,会创建一个称为执行上下文(AO或GO)的内部对象,执行上下文定义了函数的执行环境。每次函数执行时对应的执行上下文是唯一的,所以每次调用函数时都会创建一个新的执行上下文,生成的执行上下文在函数执行时会被销毁。

作用域链是存储在函数的[[scope]]属性中的运行时上下文对象的集合,这些对象链接在一个链中,我们称之为链链接作用域链。

范围链更像是一种包容关系。比如在函数A里面定义了一个函数B,那么B的定义就依赖于A,也就是说B在A里面,所以B可以访问A里面的变量和方法,这种一层一层相互依赖的关系就构成了范围链。

为了更好的理解,让我们直接看例子。

var name=' xiaoyu函数fn1(){ };函数fn2(){ var num=10;函数fn3(){ var num 1=10;console . log(num);};返回fn3} var fn4=fn2();

从前面的例子中我们知道,fn2在执行时会返回fn3,从而导致闭包。但是一个函数执行然后返回到另一个函数会产生闭包吗?让我们看看。

var name=' xiaoyu函数fn1(){ };函数fn2(){ var num=10;函数fn3() {//fn3函数不依赖于fn2函数中的变量var num1=10console . log(num 1);};返回fn3} var fn4=fn2();

了解范围链后,我们来看一个小例子来巩固它。

var age=10var obj={ age: 12,test : function(){ console . log(age);console . log(obj . age);console . log(this . age);} } obj . test();很容易理解console.log(this.age)打印12,但是为什么console.log(age)也要打印12呢?

我们说在执行测试的时候,首先会检查自己的范围内是否有年龄变量,然后沿着范围链向上到全局范围去寻找年龄变量,全局范围内有年龄变量和数据变量。因此,如果您想打印console.log(age)打印的10个中的12个,您需要访问obj.age

ES6的块级范围

ES6之后,通过let和const引入了块级范围。也就是说,let和const声明的变量只在声明它们的块级范围内有效,虽然let声明的变量属于全局变量,但它们不再属于全局对象窗口。

让我们通过一段代码来看看引入块级作用域后,函数作用域链的变化。

var age=10let obj={ age: 12,test : function(){ console . log(age);console . log(obj . age);console . log(this . age);} } obj . test();

更多资讯
游戏推荐
更多+