JS中的代码具有其 执行环境
,定义了变量或函数有权访问的其他数据,浏览器中一般的全局执行环境是对象 window
,一个执行环境中的代码执行完后就会释放其所有的变量,例如 window
在关闭网页或者关闭浏览器时销毁。
作用域 & 作用域链
代码运行时会创建一个 作用域链
,当访问变量标识符时会按照 作用域链
一级一级往上寻找变量,可以通过下面的代码简单理解。
var name = "old_8"
function changeName() {
name = "new_8"
}
changeName()
console.log(name) // 输出 new_8
在 changeName
函数代码执行时,首先会访问 window -> changeName -> arguments (执行changeName函数时创造的活动对象的执行环境)
,看看里面有没有这个 name
,发现并没有,于是从 作用域链的前端
,即 arguments
,一级一级往上找,此时发现 window
里面有个 window.name
,就拿来用了。
延长作用域链
按照上面的情况,子节点
可以一层层往上访问,而上层的代码显然不能直接使用子节点的 作用域
,可以使用这两种办法来延长作用域链:
try-catch
中的catch
块- 使用
with
关键字
下面是使用 with
关键字的例子:
function addLocalSuffix(){
var suffix = ".html"
with (location) {
var url = href + suffix // 这里的 href 即是 location.href
}
return url
}
大括号 ≠ 块作用域 👍
C++大括号里面的内容会随着代码执行完毕销毁,比如:
if (name == "yellow") {
int id = 123;
cout << id; // 可以
}
cout << id; // 不行, 会报错
但是 JavaScript 不一样,它不会形成块作用域
,无论是遇到 if、for 还是 while 产生的大括号:
for (var i = 0; i < 10; i++) {
console.log('cout << "团长你就是歌姬";')
}
console.log(i) // 输出 10