全回顾扫盲js之面向对象透过栗子看本质

function Parent2 () {
  this.list = [1,2,3]
}
function Child2 () {
  this.age = '27'
}
Child2.prototype = new Parent2()

var C1 = new Child2()
var C2 = new Child2()

console.log(C1.list)  // [1, 2, 3]
C2.list.push(4)
console.log(C1.list)      // [1, 2, 3, 4]

/****************************分割线***********************************************/
function Parent3 () {
  this.list = [1,2,3]
}
function Child3 () {
  this.age = '27'
}
var C3 = new Parent3()
var C4 = new Parent3()

console.log(C3.list)    // [ 1, 2, 3 ]
C4.list.push('4')
console.log(C3.list)    // [ 1, 2, 3 ]

如何解释这个问题,首先要明确的是,根据new方法的原理,它创造出来的是一个把父级构造函数和原型对象的属性添加到一起的字面量对象。第一个示例中,Child2的原型对象通过new方法,在原型对象上创造出了 自身的独立的list属性,但是对于再一次以Child2为构造函数创建出来的C1来说,通过new方法创建出来的属性中只有Child2这个构造函数的属性是独立的,list属性是指向Child2的原型对象的指针,所以是公共引用的。

为了证明这个问题,我们做一下改动

function Parent2 () {
  this.list = [1,2,3]
}
function Child2 () {
  this.age = '27'
  this.childList = [2,3,4]
}
Child2.prototype = new Parent2()

var C1 = new Child2()
var C2 = new Child2()

console.log(C1.list)  // [1, 2, 3]
C2.list.push(4)
console.log(C1.list)      // [1, 2, 3, 4]

console.log(C1.childList) // [ 2, 3, 4 ]
C2.childList.push('5')
console.log(C1.childList) // [ 2, 3, 4 ]

这里我给Child的构造函数添加一个ChildList属性,然后在测试它的独立性,会发现是互不影响的。

在第二个栗子中,就更好理解了。根据new字符的作用原理,将Parent3的构造函数中的属性分别创建了出来,所以是相互独立的。

关于new运算符的作用原理,看这里

随机浏览