在整个JS的整个学习周期中,作用域链是一个不太容易理解和掌握的部分,也恰恰是面试中最容易被问到的一个部分。今天就来好好的总结一个什么是作用域链。
1.什么是作用域链?
作用域链是在创建完函数的时候就已经生成的,作用域链是一条变量对象的链,它和执行上下文有关,用于在处理标识符的时候进行变量查询.
函数上下文的作用域链在函数调用的时候创建出来,它包含了活跃对象和该函数的内部[[Scope]]属性.
当JS需要查找变量X的值的时候(这个过程称为变量解析variable resolution),它会从链的第一个对象开始查找,如果这个对象有一个名为x的属性,则会直接使用这个属性的值,如果第一个对象中名为名为x的属性,JS会继续查找链上的下一个对象。如果第二个对象依然没有名为X的属性,则会继续查找下一个,以此类推。如果作用域链上没有任何一个对象含有属性x,那么就认为这段代码的作用域链上不存在x,并抛出一个引用错误(referenceError)异常
2.作用域链的例子
(function(){ var hello="hello,world"; function welcome(hi){ alert(hi); //解析到作用域链的第一个对象的属性 alert(hello); //解析到作用域链的第二个对象的属性 } welcome("It's easy"); })();
在js最顶层代码中(也就是不包括任何函数定义内的代码),作用域链由一个全局对象组成。
在不包含嵌套的函数体内,作用域链上有两个对象,第一个是定义函数参数和局部变量的对象,第二个是全局对象。
在一个嵌套的函数体内,作用域上至少有三个对象。
3.作用域链的创建规则(一般这里面试大大就会让你描述一下什么是作用域链)
- 当定义一个函数的时候(注意注意,是在定义的时候就已经存在了,不是在调用的时候才有),函数保存了一个作用域链
- 当调用这个函数的时候,它创建一个新的对象来存储它的参数或局部变量,并将这个对象添加保存至哪个作用域链上,同时创建一个新的更长的表示函数调用作用域的‘’链‘
3.当函数嵌套时,情况会发生变化,每次调用外部函数的时候,内部函数又会重新定义一遍,因为每次调用外部函数的时候,作用域链都是不同的。
举个栗子~~~~
var name=”one”; function test(){ var name=”two”; function test1(){
var name=”three”; console.log(name); //three } function test2(){
console.log(name); // two }
test1(); test2(); } test();
4.面试的大坑