继承
JavaScript 实现继承主要是依靠原型链来实现的。其基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法。
原型和实例的关系:每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针。
new 和 prototype
我们在创建对象时可以通过使用构造函数模式创建,通过new操作符创建。new函数内添加独立的属性,同时通过prototype添加共有的方法。这就是组合使用构造函数模式和原型模式创建对象。
这种构造函数与原型混成的模式,是目前在 ECMAScript 中使用最广泛、认同度最高的一种创建自定义类型的方法。可以说,这是用来定义引用类型的一种默认模式。
问题
如果出现以下情况
function test(){
this.str="word"
}
test.prototype.arr=[1,2,3]
var a=new test();
a.arr.push(4)
console.log(a.arr) //1234
var b=new test();
console.log(b.arr) //1234
修改了实例a的arr 结果实例b 的 arr也被修改了?
再看下面
function test(){
this.str="word";
this.arr= [1,2,3]
}
var a=new test();
a.arr.push(4)
console.log(a.arr) //1234
var b=new test();
console.log(b.arr) //123
修改了实例a的arr 结果实例b 的 arr没有被修改,这是正常情况
这是为什么呢?
分析
定义在构造函数的prototype属性上的方法会让它的所有示例都共享这个方法: 所以定义在prototype上的属性是共享的,由于是共享引用类型的属性,所以修改其中一个属性(a)时其他实例(b)也会被修改(和复制引用类型是一样的)
定义在构造函数内部的方法,会在它的每一个实例上都克隆这个方法: 所以在构造函数内部定义的属性在每创建一个实例时都会复制一次,也就是定义在构造函数内部的属性和方法是独立的相互不影响。无论操作实例中的哪一个都不会影响到其他实例中。