JavaScript 数据类型(值类型和引用类型)

JavaScript 中有两大类数据类型:值类型(Primitive Data Types)引用类型(Reference Data Types)

值类型(Primitive Data Types)

值类型(Primitive Data Types)也叫原始数据类型或者基础数据类型的。JavaScript 中有5种值类型:Undefined、Null、Boolean、Number 和 String。

var a = 5;
var b = a; // b 会在内存中拷贝一份独立的数据

a = 6;

// 因为 b 有一份独立的拷贝,
// 所以不会随 a 的值的变化而变化
console.log(b); // -> 5,

值类型的数据在赋值给变量后,每个变量都会拷贝一份独立的数据在内存中。向上面的列子那样给变量 b 赋值:var b = a,b 会复制一个数值s到内存中,不会因为 a 的值改变而改变。

引用类型(Reference Data Types)

引用类型(Reference Data Types)也可以笼统的说是对象(Object)类型(当然这么说并不合理,但引用类型主要指的是(Object)对象类型的值),例如:Array,Object,Function 等等。

var a = {name:'john'};
var b = a;

a.name = 'tom';

// a,b 都是指向内存中 {name:'john'} 对象的指针,
// 改变 a.name 实际上修改的是 {name:'john'} 对象的属性 name;
// 一旦引用的对象改变了,指向它的变量的值就都改变了
console.log(b.name); // -> 'tom'

b.name = 'robert';

// 改变 b.name 反过来也会影响 a.name
// 因为实际上它们引用是同一个值
console.log(a.name); // -> 'robert'

像上面示例代码中那样,先将对象{name:'john'}赋值给 变量 a var a = {name:'john'};,然后再将变量 a 赋值给变量 b var b = a;将同一个(引用类型的)值分别赋值给两个不同的变量,这两个变量不会像值类型那样拷贝两份独立的数据,而是都指向同一个内存地址中的数据(内存指针)。改变一个值,另一个也跟着改变。

引用类型值与 JavaScript 的继承

JavaScript 的继承是通过对象的原型链(prototype)来实现的,由于对象的原型链(prototype)是一个对象(引用类型的值),所以在 JavaScript 中实现对象的继承,通常我们会看到类似这样的代码:

function extend(sub,super){
	function F(){}

    F.prototype = super.prototype;
    sub.prototype = new F();
    sub.prototype.constructor = sub;
    sub.__super__ = super.prototype;

    return sub;
}

需要使用一个过度的空构造函数 F,让 F.prototype 对象复制(引用)父类 super.prototype 对象,然后创建一个 F 对象的实例,实现深拷贝(这样才会把父类 super 的所有公用方法(super.prototype)都完整的拷贝一份,而不是引用父类 super.prototype 对象)。再将这个实例赋值给子类的 prototype 对象,这样子类(sub)就继承了父类 super.prototype 对象。而这两个对象的 prototype 对象就都是独立的,再修改子类(sub)就不会影响父类(super)了。

如果只是简单的将子类 sub.prototype 指向父类 super.prototype 对象(sub.prototype = super.prototype)。这么处理,两个对象的 prototype 对象实际上都是对同一个(引用类型)对象的引用,改变其中任何一个对象的 prototype,子类(sub)和父类(super)都会发生改变,而这是我们不希望出现的。

SHARE THIS PAGE

免责声明:本站文章中的观点都是作者个人观点,并没有以任何方式反映他所属机构的意见。

发表评论