`
dacoolbaby
  • 浏览: 1254285 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

JavaScript 中的变量作用域问题

阅读更多

备注:这里的内容有转载的部分,有我自己理解的部分。

 

首先来一道题:

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变量作用域 希望对大家有帮助

    理解JavaScript变量作用域.pdf

    理解JavaScript变量作用域.pdf 本人还有几十本经典javascript书籍以及无数javascript资料,要的加我qq 568094881,本人网址:www.maoshanhai.com

    深入理解变量作用域

    当然我们知道全局变量是全局对象的属性,而局部变量是一个特殊的调用对象的属性,那么我们就可以再次关注一下变量作用域的表示法,对它进行再定义。有关作用域的新描述给理解多环境下的变量提供了一种有用的方法,它...

    基于JavaScript的变量作用域的辨析.pdf

    基于JavaScript的变量作用域的辨析.pdf

    JavaScript程序设计变量作用域共4页.pdf.zi

    JavaScript程序设计变量作用域共4页.pdf.zip

    Javascript中的作用域及块级作用域

     javascript的变量作用域,与平时使用的类C语言不同,例如C#中的代码: static void Main(string[] args) { if(true) { int number=10; } Console.WriteLine(number); }  这段代码进行编译,是无法通过的,...

    JavaScript的变量作用域深入理解

    在学习JavaScript的变量作用域之前,我们应当明确几点: a、JavaScript的变量作用域是基于其特有的作用域链的。 b、JavaScript没有块级作用域。 c、函数中声明的变量在整个函数中都有定义。 1、JavaScript的作用域链...

    浅谈Javascript变量作用域问题

    Js中的变量作用域问题: 1、没有块级作用域。Js中的变量作用域不是以{}为界的,不像C/C++/Java。 如: 代码如下:  if(true){  var name = “qqyumidi”;  }    alert(name); // 结果:qqyumidi Js会...

    一道关于JavaScript变量作用域的面试题_.docx

    一道关于JavaScript变量作用域的面试题_.docx

    深入解析JavaScript中的变量作用域

    在学习JavaScript的变量作用域之前,我们应当明确几点: •JavaScript的变量作用域是基于其特有的作用域链的。 •JavaScript没有块级作用域。 •函数中声明的变量在整个函数中都有定义。 1、JavaScript的作用域链...

    理解JavaScript变量作用域更轻松

    本文不打算深入讲解JavaScript变量作用域问题(其实本人也没有能力能把这一话题讲的深入些),也不讲“闭包”话题,本文只讨论最实用的JavaScript作用域知识点。 一、JavaScript作用域分类 JavaScript就两种作用域:...

    关于JavaScript中var声明变量作用域的推断

    一、迷思!由一段代码引发的疑惑 请看如下代码: 代码如下: for... 如果JavaScript中用var声明的变量可视为局部变量,那么能访问到这个变量的作用域就是这个变量的局部作用域。如上例,在console.log行处,依然有j、k

    关于javascript 回调函数中变量作用域的讨论

    关于回调函数中变量作用域的讨论精品推荐,大家可以参考下。

    javascript中的变量作用域以及变量提升详细介绍

    变量作用域“一个变量的作用域表示这个变量存在的上下文。它指定了你可以访问哪些变量以及你是否有权限访问某个变量。” 变量作用域分为局部作用域和全局作用域。 局部变量(处于函数级别的作用域)不像其他对面对象...

    VBScript中变量作用域

    解决了问题之后突然想到在Fdream的blog看过一篇文章《JavaScript变量无块级作用域》,似乎这两个是差不多的,在VBScript中变量同样没有块级作用域。 再次去看了那篇文章之后我也做了下试验,得到结果:在VBScript中...

    理解JavaScript作用域和作用域链

    在JavaScript中,变量的作用域有全局作用域和局部作用域两种。在代码中任何地方都能访问到的对象拥有全局作用域,一般来说以下几种情形拥有全局作用域:(1)最外层函数和在最外层函数外面定义的变量拥有全局作用域...

    JavaScript变量作用域及内存问题实例分析

    本文实例讲述了JavaScript变量作用域及内存问题。分享给大家供大家参考,具体如下: 学习要点: 1.变量及作用域 2.内存问题 JavaScript的变量与其他语言的变量有很大区别。JavaScript变量是松散型的(不强制类型)...

Global site tag (gtag.js) - Google Analytics