点击上方 高级前端进阶,回复“加群”
加入我们一起学习,天天进步
作用域:负责收集并维护由所有声明的标识符(变量)组成的一系列查询,并实施一套非常严格的规则,确定当前执行的代码对这些标识符的访问权限。
当前代码运行的环境,可访问的变量以及作用域链上的变量环境对象。
所谓标识符,就是变量、函数、属性或函数参数的名称。标识符可以由一或多个下列字符组成:
标识符中的字母可以是扩展 ASCII(Extended ASCII)中的字母,也可以是 Unicode 的字母字符,如 À 和 Æ(但不推荐使用)。
每一个执行上下文对应三个对象,分成两个不同的阶段:
var color = "blue";
function changeColor() {
let anotherColor = "red";
function swapColors() {
let tempColor = anotherColor;
anotherColor = color;
color = tempColor;
}
swapColors();
}
changeColor();
复制代码
GlobalContext: {
...window,
color: 'blue',
changeColor: fn
}
复制代码
于此同时:changeColor函数的执行上下文就是GlobalContext。
当前的执行上下文为:
changeColorContext: {
'activation object': {
anotherColor: 'blue',
swapColors: fn
},
'scope chain': [changeColorContext => GlobalContext]
}
复制代码
当前的执行上下文为:
swapColorsContext: {
'activation object': {
tempColor: 'blue'
},
'scope chain': [swapColorsContext => changeColorContext => GlobalContext]
}
复制代码
这里的color不属于当前当前执行上下文的活动对象,而是属于作用域链上GlobalContext的值。anotherColor则属于changeColorContext的。
代码执行时的标识符解析是通过沿作用域链逐级搜索标识符名称完成的。搜索过程始终从作用域链的最前端开始,然后逐级往后,直到找到标识符
比较下面两段代码,试述两段代码的不同之处
// A--------------------------
var scope = "global scope";
function checkscope(){
var scope = "local scope";
function f(){
debugger
return scope;
}
return f();
}
checkscope();
// B---------------------------
var scope = "global scope";
function checkscope(){
var scope = "local scope";
function f(){
return scope;
}
return f;
}
checkscope()();
复制代码
但是这里为什么是“local scope”
所以这里上面两种写法返回的代码结果都是:"local scope",因为js是静态作用域,因为f函数创建的时候变量对象内部的scope就是"local scope"。
dmitrysoshnikov.com/ecmascript/…
in the further explanation we’ll mainly use the concept of an environment, rather than scope,
通过环境的概念来代替scope。那scope如何和环境变量对应。个人理解如下:
scope这里指的是 outer指向父环境的变量,一直到global。执行栈ECS和当前执行上下文没有必然的联系,唯一有关系的是this指向。
执行上下文【具体会在下个文章学习】
这两种情况下,都会在作用域链前端添加一个变量对象。对 with 语句来说,会向作用域链前端添加指定的对象;对 catch 语句而言,则会创建一个新的变量对象,这个变量对象会包含要抛出的错误对象的声明。
let name = 'rod';
let name1 = 'rod';
function testWith() {
let withObject = {
name: 'rodchen',
age: '15'
}
with(withObject) {
console.log(name)
console.log(name1)
}
}
testWith()
复制代码
with语句使用var创建变量,则归属于所属函数。使用let / const,则属于block作用域。
let name = 'rod';
var name1 = 'rod';
function testWith() {
let withObject = {
name: 'rodchen',
age: '15'
}
with(withObject) {
let test = 'test'
console.log(name)
console.log(name1)
}
console.log(test)
}
testWith()
复制代码
这里所说的分别是:
挡在函数当中定义const / let的时候,这两种类型的变量是存储在当前函数的执行上下文的。如果是函数内部的{}内部创建的,则会在为当前的{}创建新的块级的变量对象。
let name = 'rod';
var name1 = 'rod';
function testWith() {
let withObject = {
name: 'rodchen',
age: '15'
}
if(1) {
let a = 1
console.log(a)
}
console.log(withObject)
}
testWith()
复制代码
chorme
firefox
这是一个函数内部没有{}里创建let / const
这是一个函数内部存在{}里创建let / const
当查找变量的时候,会先从当前上下文的变量对象中查找,如果没有找到,就会从父级(词法层面上的父级)执行上下文的变量对象中查找,一直找到全局上下文的变量对象,也就是全局对象。这样由多个执行上下文的变量对象构成的链表就叫做作用域链
关于本文
https://juejin.cn/post/6961711638978232356
The End
“在看”吗?在看就点一下吧