备注:这里的内容有转载的部分,有我自己理解的部分。
首先来一道题:
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 中,变量作用域是指变量可以被访问和修改的范围。 JavaScript 没有块级作用域,而是基于函数作用域和全局作用域的。 ...
本文探讨了JavaScript中的变量作用域问题,通过对两种变量的特性从不同角度进行分析和测试,讨论了如何控制变量作用域的有效方法。 变量作用域是JavaScript编程过程中经常遇到的问题之一,对于编程人员来说是一个...
### JavaScript 变量作用域详解 #### 一、引言 在探讨JavaScript的面向对象特性之前,理解变量作用域的概念至关重要。本篇文章旨在通过一系列示例和解释,帮助读者掌握JavaScript中的变量作用域机制。 #### 二、...
理解JavaScript变量作用域.pdf 本人还有几十本经典javascript书籍以及无数javascript资料,要的加我qq 568094881,本人网址:www.maoshanhai.com
本文将从JavaScript权威指南出发,深入探讨变量作用域的相关知识点,包括全局作用域、局部作用域、以及闭包等高级概念。 #### 二、全局作用域与局部作用域 1. **全局作用域** - 定义:在JavaScript中,如果一个...
JavaScript是一种广泛用于网页和网络应用的编程语言,其核心特性之一就是变量作用域。变量作用域决定了变量在何处可以被访问以及何时会被销毁。本文将深入探讨JavaScript中的全局变量、局部变量、变量提升、词法作用...
本文将深入探讨JavaScript中的变量作用域,以及它如何影响代码的运行和组织。 首先,我们来理解什么是变量作用域。在JavaScript中,变量作用域决定了变量在何处可以被访问和识别。主要有三种类型的作用域:全局作用...
JavaScript是一种广泛用于网页开发的脚本语言,它的函数和作用域是实现代码逻辑结构和模块...理解JavaScript中的变量作用域非常重要,它有助于避免变量命名冲突和意外的变量修改,从而编写出更加健壮和易于维护的代码。
javascript的变量作用域,与平时使用的类C语言不同,例如C#中的代码: static void Main(string[] args) { if(true) { int number=10; } Console.WriteLine(number); } 这段代码进行编译,是无法通过的,...
在学习JavaScript的变量作用域之前,我们应当明确几点: a、JavaScript的变量作用域是基于其特有的作用域链的。 b、JavaScript没有块级作用域。 c、函数中声明的变量在整个函数中都有定义。 1、JavaScript的作用域链...
JavaScript变量作用域是编程语言中一个非常核心的概念,它决定了变量在何处可被访问以及其生命周期。在这道面试题中,我们看到的是如何在不同作用域下声明和使用变量,特别是与for循环相结合的情况。 首先,我们要...
3. **块级作用域**:在ES6之前,JavaScript没有块级作用域,但ES6引入了`let`关键字,使得变量能够在特定代码块(如`if`、`for`或`while`语句内)中定义并保持其作用域限制。 - 示例: ```javascript function ...
Js中的变量作用域问题: 1、没有块级作用域。Js中的变量作用域不是以{}为界的,不像C/C++/Java。 如: 代码如下: if(true){ var name = “qqyumidi”; } alert(name); // 结果:qqyumidi Js会...
JavaScript作用域是编程中至关重要的概念,它规定了变量和函数的可见性及生命周期。JavaScript主要有两种作用域:全局作用域和局部作用域。 全局作用域是指在代码的任何位置都可以访问的变量或函数,这通常包括在最...
在 JavaScript 中,执行环境和作用域是两个非常重要和基本的概念,理解了这两个概念对于 JavaScript 中很多脚本的运行结果就能明白其中的道理了。执行环境是一个概念,一种机制,用来完成 JavaScript 运行时在作用域...
**变量作用域**: 在JavaScript中,变量可以存在于全局作用域或局部作用域。全局变量在整个程序运行期间都是可访问的,而局部变量只在定义它的函数内部有效。在ES6之前,JavaScript没有块级作用域,但ES6引入了`let`...
接着查找`fruit`,不在当前作用域,于是继续在全局作用域中找到`fruit`并使用。 而在全局环境中,当尝试访问`fruit`和`color`时,由于全局作用域的变量对象只包含`fruit`,所以`color`会导致一个`undefined`的错误...
变量作用域是程序中定义这个变量的区域。 先来看一段示例: /* 代码1 */ var scope = "global "; function checkScope() { var scope = "local "; function childCheck() { var scope = "childLocal "; ...