声明前置
- 变量的声明前置:指在变量被定义时,会在代码执行之前将变量放在最前面进行初始化。
- 函数的声明前置:会将函数声明放在代码执行之前先去生成该函数,所以函数声明受到函数提升机制的影响,所以无论放在什么位置都可以被调用。
作用域
- 每当声明一个新的函数就进入一个新的作用域下;
- 函数里需要用到的变量(或函数)首先会在自身作用域下找,找不到再逐级向上层作用域去找。
作用域链查找过程伪代码
- 分析代码,首先可根据提升机制将变量或者函数编译在最前面;
- 写出作用域链查找过程伪代码,找到每个作用域的AO、Scope;
- 根据伪代码方可分析出具体结果。
举例说明
- 变量的声明前置
console.log(a);//undefined var a = 1; console.log(a);//1
/* 声明前置分析代码 */ var a; console.log(a); //undefined a = 1; console.log(a); //变量a会声明前置,故第一次输出:undefined //第二次输出前变量a已经赋值,故第二次输出:1
- 函数声明放在任何位置都会函数声明前置,而函数表达式只有在这个表达式执行完后才会调用改函数
sayName('world'); sayAge(10); function sayName(name){ console.log('hello ', name); } var sayAge = function(age){ console.log(age); };
/* 首先还是根据函数提升机制分析代码 */ function sayName(){...} var sayAge; sayName('world'); //输出:hello world sayAge(10); //输出:sayAge is not a function sayAge = function(){..}
var x = 10; bar() ; function foo() { console.log(x); } function bar(){ var x = 30; foo(); }
/* 首先根据声明前置分析代码 */ var x; function foo(){ console.log(x); } function bar(){ var x; x = 30; foo(); } x = 10; bar(); /* 作用域链查找过程伪代码 */ globalContext{ AO:{ x:10 foo:function bar:function } Scope:{} } foo[[scope]] = globalContext.AO bar[[scope]] = globalContext.AO fooContext{ AO:{} Scope:foo[[scope]] = globalContext.AO } barContext{ AO:{ x:30 } Scope:bar[[scope]] = globalContext.AO } //输出: 10
var x = 10; bar(); function bar(){ var x = 30; function foo(){ console.log(x) } foo(); }
/* 作用域链查找过程伪代码 */ globalContext{ AO:{ x:10, bar:function }, Scope:{} } bar[[scope]] = globalContext.AO barContext{ AO:{ x:30, foo:function } scope:bar[[scope]] = globalContext.AO } foo[[scope]] = barContext.AO fooContext{ AO:{} scope:barContext.AO } //输出:30
var a = 1; function fn(){ console.log(a); var a = 5; console.log(a); a++; var a; fn3(); fn2(); console.log(a); function fn2(){ console.log(a); a = 20; } } function fn3(){ console.log(a); a = 200; } fn(); console.log(a);
/* 作用域链查找过程伪代码 */ globalContext{ AO:{ a:1->200 fn:function, fn3:function }, Scope:{} } fn[[scope]] = globalContext.AO fn3[[scope]] = globalContext.AO fnContext{ AO:{ a:5->6->20 fn2:function } scope:globalContext.AO } fn2[[scope]] = fnContext.AO fn3Context{ AO:{} scope:globalContext.AO } fn2Context{ AO:{} scope:fnContext.AO } //输出: undefined 5 1 6 20 200
作者:饥人谷fanlelee
链接:https://www.jianshu.com/p/9346423613a0