作用域链词法分析

函数内部一层一层往上找最后找到全局window ,形成的链条就叫做作用域链。

经典例题一

function t(age){
var age = 5;
console.log(age);
}
t(99);//5;

分析

一共四步:

1 任何参数执行创建AO(Active Object)对象

  t.AO = {}

2 将函数的参数作为AO的属性写入

  t.AO = {age:99}

3 分析函数内部var

  因为AO对象内部已经有了age所以舍弃内部var的声明,注意:舍去的只是声明,不舍去赋值

4 分析函数内部函数,如果有函数,则函数覆盖参数变量

  没有内部函数

分析完毕此时t.AO =  {age:99}

------------------------以上只是分析而已以下是执行-----------------------------

开始执行:

age = 5;

所以t.AO.age = 5;

所以t(99)答案为5;

经典例题2:

若函数里边有函数且函数名于参数名字相同,则函数会覆盖参数

function t(greet){
console.log(greet);
function greet(){
alert("hello");
}
}
t(3);

1参数 t.AO = {greet:3}

2 函数内var 没有

3 函数内函数 有

t.AO = {

  greet:function (){

  alert("hello");

}

}

经典例题3

function t(arg){
  (1)console.log(arg);//3
  (2)var arg= function (){//只是一个函数表达式
  alert("hello");
}
  (3)console.log(arg);//function (){alert("hello")}
}
t(3);

分析:

1 创建对象 : t.AO = {}

2 参数:        t.AO = {arg : 3}

3 函数内var,有。但是与参数同名忽略声明,注意不忽略执行

   此时  t.AO = {arg : 3}

4 函数内函数 ,没有,此时  t.AO = {arg : 3}

开始执行从上到下:

(1)执行结果为 t.AO = {arg : 3} 所以值为3

(2)执行赋值语句arg = function(){alert("hello")}

(3)执行赋值语句t.AO = {arg : function(){alert("hello")}}

注意:函数表达式优先级低于函数声明

function a(b){
(1)console.log(b);
function b(){
console.log(b);
}
b();
}
a(1);
1 a.AO = {}
2 a.AO = {b:1}
3 var 没有
4 function 覆盖
a.AO = {
b:function(){
console.log(b);
}
}
a 函数分析完成 开始执行 (1)
b 结果为function

分析内层b函数

1 b.AO = {}
2 没有
3 没有
4 没有

结果为 b.AO = {}
开始执行:b.AO 里面没有属性顺着作用域往上找 a.AO 里面的属性
找到了b:function

例题5

function a(b) {
(1)alert(b);
(2)var b = function() {
(3)alert(b);
}
b();
}
a(1);
1 a.AO = {};
2 a.AO = {b:1};
3 略去声明,不舍去赋值 a.AO = {b:1};
4 没有
执行a :

(1) = 1;
(2) 赋值 a.AO = {b:function(){alert(b)}};
// 函数在调用时候分析

分析b:
b.AO = {},b里面没有找a的
执行b:
(3) = b:function(){alert(b)}

原文地址:https://www.cnblogs.com/niuniuniu/p/6385638.html