备注:这里的内容有转载的部分,有我自己理解的部分。
首先来一道题:
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();
都是abc,看懵了吧?
慢慢来理解吧。
var a=100;
var b=true;
function test(){
alert(a); //undefined
alert(b); //true
b=false;
alert(b); //false
var a=200;
alert(a/2); //100
alert(++Math.PI); //4.14...
alert(Math.PI++); //3.14...
}
test();
这里为什么会输出undefined呢?
像javascript这样的解释型语言,基本分为两个阶段,编译期(下面为符合大多数语言的称呼习惯,改叫预编译)与运行期。
在预编译阶段,它是用函数来划分作用域,然后逐层为其以 var 声明的变量(下略称为var变量)与函数定义开辟内存空间,再然后对var变量进行特殊处理,统统赋初始值为undefined。
我们都明白局部变量的优先级大于全局变量,或者说内围作用域的变量的优先级比外围的高。
当JS引擎在当前作用域找不到此变量时,它就往外围的作用域找。
不过,在这之前,有一个严肃的问题是,究竟当前作用域存不存在这个变量。
第1行——它为外围作用域的a赋值为100
第2行——它为外围作用域的b赋值为true
第3行——进行test的作用域,我们简称为内围作用域。
第4行——就立即调用内围作用域的a,这时它还没有来得及赋值呢!
不过它已经声明过了,因此默认为其赋值为undefined(在预编译阶段,见图),
于是alert为undefined
第5行——就调用b时,JS引擎就拿起我画的图看了(笑),
发现test的作用域内没有b,眼睛往外望,发现b了,
而b在第二行就赋值为true,于是alert为true。
第6行——为一个赋值操作,把外围的b变量改赋为false。
第7行——alert为false。以下说法不说了。
那么,如果我把var a = 200;注释掉会怎样呢?
是的,那么JS引擎则在预编译阶段则找不到作用域里面的a,转而直接使用Global变量。
好的,那么复习一下:
var scope = "global";
function f() {
alert(scope);
var scope = "local";
alert(scope);
}
f();
你做对了吗?
第一个是 undefined
第二个是 local
那么再来看这个、
Object.test = "bbb";
Object.prototype.test = 'ccc';
window.test = "aaa";
(function f() {
alert(test);
})();
或许很多人会猜是bbb
但实际上呢,是aaa。
JS引擎为了速度优化,所以在所有没有声明的变量前面自动加上window.
其中的window.test 其实等同于 var test = "aaa";
另外像Object.test = “XXX”这样定义,为类属性,或称静态属性。类属性优先级都是比实例属性低的
关于prototype的使用机制在后面会给出。
再回过头来看最前面的题目:
第一个为xyz,
f.abc很明显就是调用其实例属性,通常构造函数是这样定义实例方法与实例属性的:
this.XXX = "XXXXXXXX"
(实例属性 优先级比 类属性 高)
第二个就是构造函数内部的foo.abc还是外部的foo.abc的问题了。
我们只要搞清楚一点就可以,写在外面的那个(foo.abc=function(){alert('123');})是"极晚绑定"的成员,
优先级极低,覆盖不了内部的同名成员。
第三个为什么会报错呢?!
因为在预编译阶段,
foo()的作用域就有了一个abc变量,
因此abc = function(){alert('@@@@@')}
就变不了window.abc = function(){alert('@@@@@')},
而下面那一行就更甭提了。
而我们调用的是abc,全局变量的abc,
浏览器会自动给它加上window.abc,就算不加上,
沿途的Objcet也没有abc这个变量,
因此它在f()的作用域外找不到abc,就报未定义错误!
内容参考自:http://blog.csdn.net/kingwolfofsky/article/details/6581944
http://www.cnblogs.com/rubylouvre/archive/2009/08/21/1551270.html
分享到:
相关推荐
javascript变量作用域 希望对大家有帮助
理解JavaScript变量作用域.pdf 本人还有几十本经典javascript书籍以及无数javascript资料,要的加我qq 568094881,本人网址:www.maoshanhai.com
当然我们知道全局变量是全局对象的属性,而局部变量是一个特殊的调用对象的属性,那么我们就可以再次关注一下变量作用域的表示法,对它进行再定义。有关作用域的新描述给理解多环境下的变量提供了一种有用的方法,它...
基于JavaScript的变量作用域的辨析.pdf
JavaScript程序设计变量作用域共4页.pdf.zip
javascript的变量作用域,与平时使用的类C语言不同,例如C#中的代码: static void Main(string[] args) { if(true) { int number=10; } Console.WriteLine(number); } 这段代码进行编译,是无法通过的,...
在学习JavaScript的变量作用域之前,我们应当明确几点: a、JavaScript的变量作用域是基于其特有的作用域链的。 b、JavaScript没有块级作用域。 c、函数中声明的变量在整个函数中都有定义。 1、JavaScript的作用域链...
Js中的变量作用域问题: 1、没有块级作用域。Js中的变量作用域不是以{}为界的,不像C/C++/Java。 如: 代码如下: if(true){ var name = “qqyumidi”; } alert(name); // 结果:qqyumidi Js会...
一道关于JavaScript变量作用域的面试题_.docx
在学习JavaScript的变量作用域之前,我们应当明确几点: •JavaScript的变量作用域是基于其特有的作用域链的。 •JavaScript没有块级作用域。 •函数中声明的变量在整个函数中都有定义。 1、JavaScript的作用域链...
本文不打算深入讲解JavaScript变量作用域问题(其实本人也没有能力能把这一话题讲的深入些),也不讲“闭包”话题,本文只讨论最实用的JavaScript作用域知识点。 一、JavaScript作用域分类 JavaScript就两种作用域:...
一、迷思!由一段代码引发的疑惑 请看如下代码: 代码如下: for... 如果JavaScript中用var声明的变量可视为局部变量,那么能访问到这个变量的作用域就是这个变量的局部作用域。如上例,在console.log行处,依然有j、k
关于回调函数中变量作用域的讨论精品推荐,大家可以参考下。
变量作用域“一个变量的作用域表示这个变量存在的上下文。它指定了你可以访问哪些变量以及你是否有权限访问某个变量。” 变量作用域分为局部作用域和全局作用域。 局部变量(处于函数级别的作用域)不像其他对面对象...
解决了问题之后突然想到在Fdream的blog看过一篇文章《JavaScript变量无块级作用域》,似乎这两个是差不多的,在VBScript中变量同样没有块级作用域。 再次去看了那篇文章之后我也做了下试验,得到结果:在VBScript中...
在JavaScript中,变量的作用域有全局作用域和局部作用域两种。在代码中任何地方都能访问到的对象拥有全局作用域,一般来说以下几种情形拥有全局作用域:(1)最外层函数和在最外层函数外面定义的变量拥有全局作用域...
本文实例讲述了JavaScript变量作用域及内存问题。分享给大家供大家参考,具体如下: 学习要点: 1.变量及作用域 2.内存问题 JavaScript的变量与其他语言的变量有很大区别。JavaScript变量是松散型的(不强制类型)...