容器
任何一段 JavaScript 代码都需要在一个容器中运行。可以自己创建基于容器的子容器。
一个容器中可以放置多个属性,每个属性可以引用一个对象。如以下代码:
a = 23; // 属性引用数值 b = 'hello'; // 属性引用字符串 c = new Date() // 属性引用时间 d = null; // 属性引用空对象(注意,null也是一个对象)
有一类特殊对象,Function 对象。该对象是一个容器,可以在该容器中放置多个属性。
// 设置A为一个容器 A = function () { this.a = 4; this.b = 'hello'; this.c = new Date(); this.d = null; } a = new A(); // 构造容器 a.a == 4; // true 获取容器中的数值
Function 对象同时也可以作为一个操作集合来使用。操作集合指,在 Function 中放置一系列操作过程。
// 定义一个操作集合 a = function () { var i, sum = 0; for (i=1; i<=100; i++) { sum += 0; } return sum; } b = a(); // 执行操作集合 b == 5050; // true 1加到100的值是5050
下面的代码将构成出一个容器环境:
a = 'c is undefined because b have not evaluated'; b = function() { c = 44; } D = function() { e = 30; this.f = e; } g = new D();
以上代码将构造出如下的环境,全局环境中将存在 a, b, D, e, g 四个属性,其中 g 属性引用一个容器,该容器中存放一个 f 属性。
this 与 new
JavaScript 中,如果要创建新的容器,则需要使用 new 操作符。new 操作符的执行过程为:
- 创建一个子容器
- 将 this 设置为指向创建的容器
- 执行 function 中的代码
如果没有使用 new 关键字,则不会创建子容器,而是直接执行 function 中的代码。
以下显示两者的区别:
function a1() { this.b1 = 4; return this.b1; } c1 = new a1(); function a2() { this.b2 = 4; return this.b2; } c2 = a2();
以上代码将构成如下的容器结构.
- 第一种情况,使用了 new 操作符,从而构造出一个新的容器,容器中有 b1 属性。
- 第二种情况,没有使用 new 操作符,从而 this 所指向的是调用 a2 的容器
变量与属性
变量
变量是在一个顺序的操作过程中所定义的名称,它所引用的值由运行环境决定在什么时候销毁。用户无法通过 delete 来清除掉它。
变量定义方法,在变量之前加上 var 关键字
var a = 'this is a'; var b = 32;
在操作过程中可以定义子操作过程,子操作过程如果有未定义的变量,将依次向外层提取变量。如果在最外层都没有找到变量值,则该变量是未定义变量(undefined)。
function first() { var a = 1; var b = 1; function second() { var a = 2; a == 2; // a 在 second 中可以找到 b == 1; // second 中没有找到 b, 在外层 first 中找到 c == undefined; // c 在 first 之中、之外都没有没有定义 } second(); b == undefined; // b 在 first 之中、之外都没有没有定义 } first();
属性
属性指一个容器(通过 new 构造出来的或者全局容器)中的属性。属性的定义方法:指定属性的对象:
this.a = 32; // 指定当前容器的 a 属性 b = {}; // 构造一个容器 b.a = 'string'; // 指定容器的 a 属性
全局容器可以不指定容器
a = 4; // 设定全局容器的 a 属性 b = 'global container'; // 设定全局容器的 b 属性
用户可以通过 delete 操作来删除一个容器中的属性。
综合
以下代码显示属性和变量综合使用的情况:
var c = 10; d = 20; function A() { this.a = 42; c == 10; // 操作环境中没有c,取外层变量c的值 b == undefined; // 操作环境及外层都没有b d = 21; // 操作环境中没有d,给外层容器的属性d赋值 b = 37; // 操作环境中没有b,给外层容器的属性d赋值。全局容器不需要指定属性所在的容器, c = 16; // 操作环境中没有c,给外层变量c赋值 } a1 = new A(); var a2 = new A(); b == 37; // 容器A中将b的值改变为37 c == 16; // 容器A中将c的值改变为16 delete b; delete c; b == undefined; // 用户可以删除容器中的一个属性 c == 16; // 变量的销毁由运行环境决定,用户无法删除 delete a1; delete a2; a1 == undefined; // 用户可以删除全局容器中的属性(它引用的是一个对象) typeof(a2) == 'object'; // 用户不能删除全局容器中的变量
prototype 属性
prototype 属性是任何一个容器都拥有的属性,该属性所引用的是一个容器。引用一个容器中的属性,会按如下顺序来引用:
function A() { this.a = 4; } A.prototype.a = 6; A.prototype.b = 6; var c = new A(); c.a == 4; // 首先查找A容器中的属性 c.b == 6; // 然后查找A容器的prototype属性对应的容器是否有对应的属性 c.c == undefined; // 如果都没有,则为 undefined
通过该特征,可以为 String 添加一个方法例如:
String.prototype.hello = function() { alert(this); } '12345'.hello();
方法继承
如果需要将一个类中的所有方法都让另外一个类继承,可以如下:
function A(a) { this.c = a; this.a = function() { alert('a'); } this.b = function() { alert('b'); } } function B(a) { var aa = new A(a); for (var i in aa) { this[i] = aa[i]; } this.d = function() { alert(this.c); } } var b = new B(); b.a(); b.d();