知识点一:在函数体内,局部变量的优先级高于同名的全局变量。如果在函数内声明的一个局部变量或者函数参数中带有的变量和全局变量重名,那么全局变量就会被局部变量遮盖。
知识点二:JavaScript中没有块级作用域,但有函数作用域。变量在声明它们的函数体以及这个函数体嵌套的任意函数体内都是有定义的。
知识点三:声明提前不等于赋值也提前。
var scope = "global"; function f() { console.log(scope);//undefined var scope = "local"; console.log(scope);//local } f();
等同于:
var scope = "global"; function f() { var scope; console.log(scope);//undefined scope = "local"; console.log(scope);//local } f();
注意:区别以下代码中scope始终是全局变量
var scope = "global"; function f() { console.log(scope);//global scope = "local"; console.log(scope);//local } f();
知识点四:作用域链 --目的是为了理解闭包
开始我们先从示例来导入:
var name1 = "haha"; function changeName(){ var name2="xixi"; function swapName(){ console.log(name1);//haha console.log(name2);//xixi var tempName=name2; name2=name1; name1=tempName; console.log(name1);//xixi console.log(name2);//haha console.log(tempName);//xixi } swapName(); console.log(name1);//xixi console.log(name2);//haha //console.log(tempName);抛出错误:Uncaught ReferenceError: tempName is not defined } changeName(); console.log(name1);//xixi //console.log(name2); 抛出错误:Uncaught ReferenceError: name2 is not defined //console.log(tempName);抛出错误:Uncaught ReferenceError:tempName is not defined
运行结果如下:
haha
xixi
xixi
haha
xixi
xixi
haha
xixi
上述代码中,一共有三个执行环境:全局环境、changeName()的局部变量和swapName()的局部环境。
由此可见:
1.函数 swapName()的作用域链包含三个对象:自己的变量对象----->changeName()局部环境的变量对象 ----->全局环境的变量对象。
2.函数changeName()的作用域包含两个对象:自己的变量对象----->全局环境的变量对象。
就上述程序中出现的变量和函数来讲(不考虑隐形变量):
1.swapName() 局部环境的变量对象中存放变量 tempName;
2.changeName() 局部环境的变量对象中存放变量 name2 和 函数swapName();
3.全局环境的变量对象中存放变量 name1 、函数changeName();
值得注意的是:函数的局部环境可以访问函数作用域中的变量,也可以访问和操作父环境(包含环境)乃至全局环境中的变量。
作用域链相关知识的总结:
1.执行环境决定了变量的生命周期,以及哪部分代码可以访问其中变量
2,执行环境有全局执行环境(全局环境)和局部执行环境之分。
3.每次进入一个新的执行环境,都会创建一个用于搜索变量和函数的作用域链
4.函数的局部环境可以访问函数作用域中的变量和函数,也可以访问其父环境,乃至全局环境中的变量和环境。
5.全局环境只能访问全局环境中定义的变量和函数,不能直接访问局部环境中的任何数据。
6.变量的执行环境有助于确定应该合适释放内存。