js作用域
文章类型:Javascript
发布者:admin
发布时间:2023-02-24
作用域: 定义变量的区域,变量访问规则用来管理浏览器引擎如何在当前作用域以及嵌套的作用域中根据变量(标识符)进行变量查找
1:词法作用域,定义在词法阶段的作用域,也就是说些代码时将变量和块级作用域编写的位置决定,在定义时的环境中去查询
2:动态作用域,运行的时候才决定,,在调用时的环境中去查询
作用域链:块或函数嵌套在另一个块或函数中时,就发生了作用域的嵌套,无法找到就会在外层继续找
1: 保证对执行环境有权访问的所有变量和函数的有序访问,通过作用域链,我们可以访问到外层环境的变量和 函数。
2:本质是指向变量对象的指针列表,变量对象是包含了执行环境中所有变量和函数的对象。
3:作用域链的前端始终都是当前执行上下文的变量对象。全局执行上下文的变量对象(也就是全局对象)始终是作用域链的最后一个对象
作用域分为:
1:全局作用域
挂载在window对象下面的变量,在网页任何位置都可以访问并且使用,
var globalName = 'global';
function getName() {
console.log(globalName) // global
var name = 'inner'
console.log(name) // inner
}
挂在载全局,可以在任意地方使用
但是定义多个全局变量,一方面容易导致命名冲突,解耦低,
另外一方面还可能导致内存泄漏,因为全局变量挂在window下,不会被垃圾回收机制回收
2:函数作用域
函数中定义的变量,只能在函数内部访问它,使用范围局限在函数内部
function getName () {
var name = 'inner';
console.log(name); //inner
}
getName();
console.log(name); //undefined
3:块级作用域
es6新增块级作用域,只能在某个块级范围内使用,由最近的{}决定范围,也称作“暂时性死区”,声明前不可用,es6中新增的let,let 在全局作用域中声明的变量不会成为 window 对象的属性
console.log(a) //a is not defined
if(true){
let a = '123';
console.log(a); // 123
}
console.log(a) //a is not defined
4:作用域链,
从最前端开始,然后逐级往后,直到找到标识符
let color = "blue";
const color_b = 'red'
function changeColor() {
let color = 'yellow'
console.log(color)//yellow
const color_b = 'black'
console.log(color_b)//black
}
changeColor();
console.log(color)//blue
console.log(color_b)//red
5:词法作用域
function foo(){
console.log(a); //2
}
function bar(){
var a = 3;
foo();
}
var a = 2;
bar();
6:动态作用域
var scope = "global scope";
function checkscope(){
var scope = "local scope";
function f(){
return scope;
}
return f();
}
checkscope(); //local scope
7:欺骗词法,eval和with,大量使用会导致性能问题
with 可以将一个没有或有多个属性的对象处理为一个完全隔离的词法作用域,因此这个对 象的属性也会被处理为定义在这个作用域中的词法标识符
eval(…) 函数如果接受了含有一个或多个声明的代码,就会修改其所处的词法作用域,
而 with 声明实际上是根据你传递给它的对象凭空创建了一个全新的词法作用域,简单来说就是写代码的位置
function foo(str, a) {
eval( str ); // 欺骗!
console.log( a, b );
}
var b = 2;
foo( "var b = 3;", 1 ); // 1, 3
var obj = { a: 1, b: 2, c: 3};
// 单调乏味的重复 "obj"
obj.a = 2;
obj.b = 3;
obj.c = 4;
// 简单的快捷方式
with (obj) {
a = 3;
b = 4;
c = 5;
}
//{a: 3, b: 4, c: 5}
function foo(obj) {
with (obj) {
a = 2;
}
}
var o1 = {
a: 3
};
var o2 = {
b: 3
};
foo(o1); console.log(o1.a); // 2
foo(o2); console.log(o2.a); // undefined
console.log(a); // 2