第5章 变量与对象


5.1 变量的声明

变量的功能为持有某个值,或者用来表示某个对象。

// 如果一个变量在声明之后没有进行赋值,它的值就会是undefined。
// 对同一个变量重复进行声明是不会引起什么问题的,原有的值也不会被清空。
var hzh1 = 7;
console.log("输出hzh1的值:");
console.log(hzh1);
// 即使对同一个变量重复进行声明
var hzh1;
// 它的值也不会发生改变
console.log("输出变量hzh1的值:");
console.log(hzh1);
// 如果变量 a 具有某个可以被转换为 true 的值就直接使用,
// 否则就把 7 赋值给a
console.log("输出变量hzh2的值:");
var hzh2 = hzh2 || 7;
// 如果 a 是一个已经被声明且赋值的变量,则不会有任何效果;
// 而如果没有被声明过,则会在声明的同时对其进行赋值操作。
/*************************************************************/
// 如果变量 b 没有被声明过,将会引起 ReferenceError 异常。
// 不过,也不能说它绝对就是错的。
// 这是因为,如果能确保在这条代码之前就已经对变量 b 进行了声明,
// 这段代码的作用就变为了判定变量 b 的值的真假,这样就没有问题了。
var hzh3 = hzh4 || 7;
console.log("输出变量hzh3的值:");
console.log(hzh3);

5.2 变量与引用

对象的概念很好地说明了变量是一种拥有名称的客体。对象本身是没有名称的,之所以使用变量,是为了通过某个名称来称呼这样一种不具有名称的对象。

变量又分为基本类型的变量(值型变量)与引用类型的变量。由于在 JavaScript 中,变量是不具有类型的,因此从语法标准上来看,两者并没有什么不同。不过,在 JavaScript 中仍然有对象的引用这一概念。

所谓“引用”,可以认为是一种用于指示出对象的位置的标记。如果你熟悉 C 语言,把它理解为是和指针等价的东西也没有问题。不过,引用不支持那些可以对指针进行的运算。引用这一语言功能只有指示位置信息的作用。准确地说,对象的赋值其实是将对象的引用进行赋值。

为了更好地解释引用这一概念,这里对引用类型的变量和值型变量进行比较。将基本类型的值赋值给变量的话,变量将把这个值本身保存起来。这时,可以将变量简单地理解为一个装了该值的箱子。变量本身装有所赋的这个值,所以能够将该值从变量中取出。如果在右侧写上一个变量,这一变量的值将被复制给赋值目标处(左侧)的变量。

var a = 123;    // 将数值123赋值给变量a
var b = a;      // 将变量a的值(数值123)赋值给变量b
console.log("第一次输出变量a的值:");
console.log(a); 
console.log("第一次输出变量b的值:");
console.log(b); 
b++;
console.log("");
console.log("第二次输出变量a的值:");
console.log(a); 
console.log("第二次输出变量b的值:");
console.log(b); 

var a = { x:1, y:2 }; // 将对象的引用赋值给变量a
var b = a;            // 将变量a的值(对象的引用)赋值给变量b
console.log("输出变量a的值:");
console.log(a);
console.log("输出变量b的值:");
console.log(b);
console.log("*******************************************");
// 如果像下面这样,改变了变量 b 所引用的对象,
// 那么这一改变也会体现在变量 a 之中,
// 这是因为这两个变量通过引用而指向了同一个对象
b.x++;            // 改变变量b所引用的对象
console.log("输出变量b的x属性:");
console.log(b.x); // 变量b所引用的对象
console.log("输出变量a的x属性:");
console.log(a.x); // 可以发现变量a所引用的对象也被改变

// 对于引用类型的变量,
// 整个过程中发生改变的其实是其引用的对象,而不是该变量的值。
// 引用类型的变量具有的值就是引用(值),
// 这个值将在赋值的时候被复制
var a = { x:1, y:2 };
var b = a;        // 变量a与变量b引用的是同一个对象
a = { x:2, y:2 }; // 改变了变量a的值(使其引用了另一个对象)
console.log("输出变量b的x属性:");
console.log(b.x); // 变量b所引用的对象没有发生改变
// 在 JavaScript 中,赋值运算总是会把右侧的值复制给左侧。
// 对于引用类型的变量来说也是一样,会将引用(用于指示对象的一种值)赋值给左侧。
// 函数调用过程中的参数也是这样的执行方式。

5.2.1 函数的参数(值的传递)

5.2.2 字符串与引用

5.2.3 对象与引用相关的术语总结

5.3 变量与属性

5.4 变量的查找

5.5 对变量是否存在的校验

5.6 对象的定义

5.6.1 抽象数据类型与面向对象

如果从形式上来定义 JavaScript 的对象,它就是一种属性的集合。所谓属性,即名称与值的配对。属性值可以被指定为任意类型的值,包括数组或其他的对象,都没有问题。

对于对象有一种很常见的定义,即它是一种数据和操作(子程序)的结合。这一定义可以理解为,将面向对象看作一种抽象数据类型的表现形式。

面向对象的 3 要素,即封装、继承与多态吧。如果这样理解的话,面向对象程序设计的焦点就在于对象的执行方式,并将执行方式的共性定义为一种类型。

在这一语境中,常常使用类这一术语来表达类型的含义。也有些语言会把执行方式与其实现分开,将执行方式定义为接口。接口的实例(实体)被称为对象,可以对其进行指定的操作。

5.6.2 实例间的协作关系与面向对象

另一种面向对象程序设计的观点认为,与其考虑执行方式之间的共性,更应该关注实例之间的协作关系,即所谓的对象是进行消息收发的实体。对象收到消息之后将会对其作出响应。从实现的角度来看,消息的实质就是通过对方法(函数)进行调用,将对消息的响应分派给方法来处理。从本质上来说,面向对象这一术语只不过是一种在高于内部实现的语境中所使用的、较为抽象的概念而已。打个比方,可以把消息当作一种通信协议,把对象当作一个 Web 应用。

5.6.3 JavaScript 的对象

JavaScript 语言所支持的面向对象与后者的理解更为相近。在JavaScript 中,一切都是对象。对象之间的协作(消息收发)通过属性访问(以及方法的调用)来实现。而对象之间的共性,则是通过继承同一个对象的性质的方式来实现。JavaScript通过基于原型的形式来实现继承。

一旦要对面向对象的概念进行说明,事情就会变得很抽象。如果只考虑具体该如何使用 JavaScript 的对象,就不必考虑那么多复杂的问题。只需要考虑最核心的内容,将其理解为在程序中可以进行操作的数据的一种扩充即可。此外,还可以通过函数方法的形式来表示对数据进行操作的子程序。这种想法的核心就是将对象的功能进行拆分并分别进行处理。分割本身也只不过是一种手段。毕竟,面向对象方法的最终目的是降低程序的复杂程度。

5.7 对象的生成

5.7.1 对象字面量

作为 singleton 模式的用法

作为多值数据的用法

用于替代构造函数来生成对象

5.7.2 构造函数与 new 表达式

5.7.3 构造函数与类的定义

5.8 属性的访问

5.8.1 属性值的更新

5.8.2 点运算符与中括号运算符在使用上的区别

5.8.3 属性的枚举

5.9 作为关联数组的对象

5.9.1 关联数组

5.9.2 作为关联数组的对象的注意点

5.10 属性的属性

5.11 垃圾回收

5.12 不可变对象

5.12.1 不可变对象的定义

5.12.2 不可变对象的作用

5.12.3 实现不可变对象的方式

5.13 方法

5.14 引用

5.14.1 this 引用的规则

5.14.2 this 引用的注意点

5.15 apply与call

5.16 原型继承

5.16.1 原型链

5.16.2 原型链的具体示例

5.16.3 原型继承与类

5.16.4 对于原型链的常见误解以及 proto 属性

5.16.5 原型对象

5.16.6 ECMAScript 第 5 版与原型对象

5.17 对象与数据类型

5.17.1 数据类型判定(constructor 属性)

5.17.2 constructor 属性的注意点

5.17.3 数据类型判定(instance 运算与 isPrototypeOf 方法)

5.17.4 数据类型判定(鸭子类型)

5.17.5 属性的枚举(原型继承的相关问题)

5.18 ECMScript第5版中的Object类

5.18.1 属性对象

5.18.2 访问器的属性

5.19 标准对象

5.20 Object类

5.21 全局对象

5.21.1 全局对象与全局变量

5.21.2 Math 对象

5.21.3 Error 对象

相关