浅析JS全局变量与局部变量 执行环境 作用域链 JS解释器执行过程

参考[url]http://hi.baidu.com/cjry_8854/item/585b445f577aab3494eb0513[/url]
这里列出几个值得注意的地方
一全局变量 变量的声明
JS解释器开始运行时,在执行任何JS代码前,会创建一个全局对象,并且JS解析器会在相应的代码段里寻找var声明的变量,把这个var声明的变量作为全局对象的属性(在函数中它也作为调用对象的属性),并初始化为undefined。

也就是说当var声明一个JS全局变量时,实际上就是定义了一个全局对象的属性,或者反过来说,这个全局对象的属性就是JS全局变量。当然JS解释器还会用预定义的值和函数来初始化全局对象的许多属性,如:Infinity parseInt Math。在非函数内部可以用this来引用这个全局对象,还要注意window和this的区别,在客户端的JS中,Window对象代表浏览器窗口,它包含该窗口中的所有JS代码的全局对象,具有自我引用的window属性。

重复的var声明不会造成任何错误 var声明只是方便创建全局对象,调用对象的属性,代码只是赋值用的

遗漏的声明:给未声明的变量赋值,JS会隐式声明全局变量(在全局对象中增加相应的属性),然后给其赋值

二.变量作用域
1.局部变量和全局变量同名时,会隐藏这个全局变量。
2.函数没有块级作用域,函数中声明的变量,无论在哪里声明的,在整个函数中它们都是有定义的。
3.未声明的变量和未赋值的变量:alert(u);会产生一个错误--使用未声明的变量会产生一个错误
var u;alert(u);会跳出undefined---使用未赋值的变量,使用的它的默认值undefined

三 局部变量:调用对象
1.函数的局部变量作为调用对象的属性,调用对象是一个完全独立的对象,它独立于全局对象,所以可以防止覆盖同名的全局变量。

四 JS的执行环境
1.JS解释器执行一个函数时,会创建一个执行环境。JS允许同时存在多个全局执行环境,如:JS客户端的ifame的情况。

执行环境定义了变量或函数有权访问的其他数据,决定了他们各自的行为。每个执行环境都有一个与之相关联的变量对象,执行环境中定义的所有变量和函数都保存在这个对象中。虽然我们编写的代码无法访问这个对象,但解析器在处理数据时会在后台使用它。作用域链的用途,是保证对执行环境有权访问的所有变量和函数的有序访问。
可见[url]http://blog.163.com/tracy_hyq/blog/static/2084161872012529112624447/[/url]
这里要注意,在上面的博客中和一些其他书籍中所说的变量对象就可以理解为这里的全局对象和调用对象,那里的活动对象可以理解为这里的调用对象。

五JS的执行过程
具体可参见[url]http://hi.baidu.com/cjry_8854/item/585b445f577aab3494eb0513[/url]

在JS解释器执行任何代码之前,创建全局对象
用预定义的值和函数来初始化全局对象中的属性,eg.Math,Infinity,parseInt
搜索函数外的var声明,创建全局对象相应的属性,初始化为undefined
创建全局的执行环境,作用域链只有一个对象-全局对象
依次执行代码
遇到var声明赋值语句给全局对象相应的属性赋值
遇到未声明赋值语句,在全局对象中查找是否已有该属性,如果没有,增加相应的属性,最后赋值
遇到函数调用,创建调用对象
搜索函数中的var声明和参数,创建调用对象相应的属性,初始化为undefined
创建函数执行环境,作用域链--第一对象:调用对象;第二对象:全局对象
依次执行代码
遇到var声明赋值语句给调用对象相应的属性赋值
遇到未声明赋值语句,在全局对象中查找是否已有该属性,如果没有,增加相应的属性,最后赋值
遇到函数调用,创建嵌套函数的调用对象
搜索嵌套函数中的var声明和参数,创建嵌套函数的调用对象相应的属性,初始化为 undefined
创建嵌套函数执行环境,作用域链--第一对象:嵌套函数的调用对象;第二对象:调用 对象;第三对象:全局对象

我的总结,先创建变量对象,搜索代码,找寻声明的赋值语句(注意是用var声明的赋值语句,未用var声明的赋值语句的属性在执行时才加入到全局对象中),创建执行环境、作用域,依次执行代码。

同时我们还应该注意
第一:在javascript的预解析中,除了对var 变量的预定义,还包括了提取对函数的定义,所以可以在script的任何地方定义函数,在任何地方调用。不限于它之前,而JS还有种函数的定义方式为字面量定义法,如
alert(typeof y3); //结果为undefined
var y3 = function (){
console.log('1');
}

javascript 引擎在预解析 var 时 会给他们一个初始值 undefined,这样一来,如果我们在它的声明之前调用它,javascript 引擎还没拿到它的真实值,自然会报"xxx is not a function" 的错。
这就是为什么函数的调用一定要在函数的字面定义法的声明之后的原因了。
第二:javascript 在预解析时function的声明优先级比var的高。
alert(typeof y5);
var y5 = 'angle';
function y5(){
console.log('ghost');
}
alert(y5);
/*首先同样的y5,由于function的声明优先级高,所以其弹出的类型为function,但是当第二次alert时,其值已赋值为angle。
*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值