JavaScript作用域学习笔记(ife2015spring学习心得)
本文参照以下两位前辈的文章,加上自己的见解,有错误之处还望大家指出
为什么要理解作用域
初学js便听人说这门语言作用域比较特殊,与c/c++实现的方式不大相同,下面就遇到问题了
遇见的问题
1 var name="xiaoming" 2 function show(){ 3 console.log(name); 4 var name="WebWhiteCoder"; 5 var age; 6 console.log(name); 7 console.log(age); 8 } 9 show();
按照一般的想法,输出的结果应该是这样的
xiaoming
WebwhiteCoder
undefined
但实际情况呢?
此时第一行声明的全局变量name却变成了undefined,function内的name却正常输出,原因何在?
答案是js的作用域链
js的作用域链:
在介绍作用域链之前,大家一定都明白这句话:js中一切皆为对象.上文那段代码定义的函数也是一个对象。
js解析器不是自上而下的一条一条按照顺序来解析代码。
原因:echo函数被调用的时候,echo的活动对象已经被创建
[callObj]={
name:undefined;
}
这时候活动对象已经存在了一个name属性,且是undefined。此时全局变量中的name就被覆盖了。
注意:函数的scope属性是在定义完函数就决定了的,而不是调用的时
function factory() { var name = 'laruence'; var intro = function(){ alert('I am ' + name); } return intro; } function app(para){ var name = para; var func = factory(); func(); } app('eve');
输出的结果:
I am laruence
先把这几个函数的作用域链上的活动属性写出来吧
app:
para:eve;
name:undefined;
func:undefined;
factory:
name:undefined;
intro:undefined;
那么问题来了,这个时候为什么name是undefined,明明已经对其赋值了啊?这里引用鸟哥的描述 在调用函数执行之前, 会首先创建一个活动对象, 然后搜寻这个函数中的局部变量定义,和函数定义, 将变量名和函数名都做为这个活动对象的同名属性, 对于局部变量定义,变量的值会在真正执行的时候才计算, 此时只是简单的赋为undefined。
无疑,这时候的name是一个局部变量,只有在真正执行的时候,也就是用到name的时候才会考虑到值,此时只是简单的赋给他undefined;
intro:
name:laruence;
此时用alert弹出name的值了吧,那么此时name就取得值。
头疼的预编译:
众所周知,js有变量提示的特性.如下面这个例子:
alert(name); var name="WebWhiteCoder";
这时候正常弹出值:WebWhiteCoder.这就是因为变量提示的特点。
函数定义式也具有这个特点,但函数表达式就不行了.
<script> alert(typeof eve); //结果:function alert(typeof walle); //结果:undefined function eve() { //函数定义式 alert('I am Laruence'); }; var walle = function() { //函数表达式 } alert(typeof walle); //结果:function </script>