javscript变量作用域
2012-10-19 18:22 露珠的微笑 阅读(465) 评论(0) 收藏 举报总算把这疑问解决啦。从入职到现在一直很困惑.看了司徒正美的博客才总算明白,以下摘抄来自司徒正美博客《javascript变量的作用域 》,个人观点文章分析得非常好:
像javascript这样的解释型语言,基本分为两个阶段,编译期(下面为符合大多数语言的称呼习惯,改叫预编译)与运行期。在预编译阶段,它是用函数来划分作用域,然后逐层为其以 var 声明的变量(下略称为var变量)与函数定义开辟内存空间,再然后对var变量进行特殊处理,统统赋初始值为undefined
主要抓住一点:预编译为var变量与函数定义分配空间,有初值赋初值,没有的默认为Undefined,
然后按Js代码逐行执行
例子1:
var a=100; var b=true; function test(){ alert(a);//由于test函数用var声明了a,所以逐行执行时访问的是内围变量a,该内围变量还未赋值,js对末赋值的变量默认为undefined alert(b);// 逐行执行到该行时,由于test函数作用域未用var声明b,所以js向外查看,外围有声明就用外围的b,外围若没声明就会报错:未定义b
b=false; // 逐行执行到该行时,b的值被test作用改变了,所以此时b=true
alert(b); var a=200; //内围变量a,逐行执行到这才赋值 alert(a/2); //访问已赋值的内围变量a } test();
执行结果为:undefined,true,false,100
分析:预编译为为var变量与函数定义分配空间,总共两个外围var变量a,b;一个内围变量a和一个函数,如下:

详细参考:司徒正美博客《javascript变量的作用域 》:http://www.cnblogs.com/rubylouvre/archive/2009/08/21/1551270.html
例子2:
Object.prototype.test = 'wrong'; var test = 'right'; (function f() { alert(test); })();

例子3:
Object.test = "bbb"; Object.prototype.test = 'ccc'; window.test = "aaa"; (function f() { alert(test); })();估计有很多人猜是bbb,其实是ccc!有人就不解了,不是对象的属性的优先级比其原型属性的优先级高吗???
无错,的确如此,不过对象的属性是这样定义的:
var o = {test:"eee"}
Object.test = “XXX”这样定义,为类属性,或称静态属性。类属性优先级都是比实例属性低的

例子4
function foo(){ foo.abc = function(){alert('def')} this.abc = function(){alert('xyz')} abc = function(){alert('@@@@@')}; var abc = function(){alert('$$$$$$')} } foo.prototype.abc = function(){alert('456');} foo.abc = function(){alert('123');} var f = new foo(); f.abc(); foo.abc(); abc();
第一个为xyz,f.abc很明显就是调用其实例属性,通常构造函数是这样定义实例方法与实例属性的:
this.XXX = "XXXXXXXX"
第二个就是构造函数内部的foo.abc还是外部的foo.abc的问题了。我们只要搞清楚一点就可以,写在外面的那个是极晚绑定的成员,优先级极低,覆盖不了内部的同名成员。
第三个为什么会报错呢?!因为在预编译阶段,foo()的作用域就有了一个abc变量,因此abc = function(){alert('@@@@@')}就变不了window.abc = function(){alert('@@@@@')},而下面那一行就更甭提了。而我们调用的是abc,全局变量的abc,浏览器会自动给它加上window.abc,就算不加上,沿途的Objcet也没有abc这个变量,因此它在f()的作用域外找不到abc,就报未定义错误!
归纳:
JS引擎有两个设置变量的机会。第一次在预编译时期,所有var变量会分配到各自的作用域中,值一律为undefined。第二次在运行期,由于是逐行执行,因此是可变的
浙公网安备 33010602011771号