今天看了js的作用域的知识,感觉收益匪浅,首先对于js的作用域,在程序执行的时候,有一句话一定要理解那就是
js函数运行在他定义时的作用域,而不是他们被执行的作用域里。
这句话一定要理解,下面来看个例子
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");
然后我们来看看作用域链,当调用app的时候,scope chain是由{window活动全局对象}-》{app的活动对象}组成。
在刚进入app函数的函数体的时候,app活动对象有一个arguments属性,两个值为undefined属性:name和func和一个值为“eve”的属性para,此时的scope chain如下:
[[scope chain]] = [
{
para : 'eve',
name : undefined,
func : undefined,
arguments : []
}, {
window call object
}
]
当进入factory的函数体的时候。此时sfactory的scope chain为
[[scope chain]] = [
{
name : undefined,
intor : undefined
}, {
window call object
}
]
注意到,此时的作用域链并不包含app的活动对象,在定义intro函数的时候,intro函数的scope chain为
[[scope chain]] = [
{
name : 'laruence',
intor : undefined
}, {
window call object
}
]
从factory函数返回之后,在app体内调用了intor的时候,发生了标识符解析,scope chain为
[[scope chain]] = [
{
intro call object
}, {
name : 'laruence',
intor : undefined
}, {
window call object
}
]
因为scope chain中并不包含factory对象,所以name属性包含的是factory中活动的name属性,也就是’laruence’.
I am laruence
现在大家对函数是运行在定义时的作用域,而不是运行他们被执行的作用域里应该有个全面的了解。
js里的预编译
js里面其实是有一个预编译的过程的,这里有两个要点:
1.声明式的函数会被预编译。
看下面这个例子:
<script>
alert(typeof eve); //function
function eve() {
alert('I am Laruence');
};
</script>
alert出来是有值的
<script>
alert(typeof eve); //结果:function
alert(typeof walle); //结果:undefined
function eve() { //函数定义式
alert('I am Laruence');
};
var walle = function() { //函数表达式
}
alert(typeof walle); //结果:function
</script>
看这个walle就是未定义的。
2.函数是分块进行编译,但是共享变量等。
看这个例子:
<script>
alert(typeof eve); //结果:undefined
</script>
<script>
function eve() {
alert('I am Laruence');
}
</script>