面向对象类

2018-03-08  本文已影响0人  G莫_小语

类与实例

类的声明
  // 类的声明
  function Animal() {
    this.name = 'jack'
  }
// 实例化
let a = new Animal()
  // 类的声明
  class Animal2 {
    constructor() {
      this.name = 'jack'
    }
  }
  // 实例化
  let a = new Animal2()

生成实例

类与继承

如何实现继承
继承的几种方式
  1. 借助构造函数
function Parent1() {
  this.name = 'parent1'
}
Parent1.prototype.say = function () { } // Child1的实例没法继承原型链上的属性方法

function Child1() {
  Parent1.call(this)  // 改变 this 上下文,Parent1构造函数的this指向Child1构造函数的实例
  this.type = 'child1'
}
let person = new Child1  // {name: "parent1", type: "child1"}
person.say()  // 报错

  1. 借助原型链实现继承
function Parent() {
  this.name = 'parent'
  this.play = [1, 2, 3]
}
Parent.prototype.say = function () { }
function Child() {
  this.type = 'child'
}
Child.prototype = new Parent()  // 重点
let s1 = new Child()
let s2 = new Child()
s1.play.push(4) // s2 也变成了 [1, 2, 3, 4]
// 缺点:本来只想改变 s1 ,但 s2 也跟着改变了,两个实例对象应该隔离无关

  1. 组合继承方式
function Parent() {
  this.name = 'parent'
  this.play = [1, 2, 3]
}
Parent.prototype.say = function () { }
function Child() {
  Parent.call(this)
  this.type = 'child'
}
Child.prototype = new Parent()
let s1 = new Child()
let s2 = new Child()
s1.play.push(4)  // 没有改原型链上的,改的是自己的,call执行时赋值,原型链上也有play

  1. 组合继承优化一
function Parent() {
  this.name = 'parent'
  this.play = [1, 2, 3]
}
Parent.prototype.say = function () { }
function Child() {
  Parent.call(this)  // 已经拿到父类里的方法属性了,后面不需要再new,只需要把父类原型上的东西也继承过来
  this.type = 'child'
}
Child.prototype = Parent.prototype  // 把父类原型上的东西也继承过来
Child.prototype.age = 33  // 父类的原型也添加了age属性,子类改变父类不应该改变
let s1 = new Child()
let s2 = new Child()
s1.play.push(4)
console.log(s1.constructor)  // Parent
console.log(s2.constructor)  // Parent
// 因为Child实现继承的时候把Parent原型里的constructor属性也继承过来了,
// 而Parent原型里的constructor属性指向的肯定是Parent,所以出现了混乱
// 实际应该指向Child
// 实例的构造函数都指向了Parent,无法确定实例的构造函数
  1. 如果给子类原型添加属性方法的话父类的原型也会跟着添加,不符合逻辑,子类不应该影响父类
    2.实例的constructor属性应该指向child构造函数,这样才符合预期要求

  1. 组合继承优化二
function Parent() {
  this.name = 'parent'
  this.play = [1, 2, 3]
}
Parent.prototype.say = function () { }
function Child() {
  Parent.call(this)
  this.type = 'child'
}
Child.prototype = Object.create(Parent.prototype)  // 现在子类改变了父类不会改变
Child.prototype.constructor = Child  // 手动设置一个构造函数,这里如果第三项照这样改的话改的是父类的constructor,而不是子类的constructor
Child.prototype.age = 33  // 父类的原型也没有添加
let s1 = new Child()
let s2 = new Child()
s1.play.push(4)
console.log(s1.constructor)  // Child
console.log(s2.constructor)  // Child
上一篇 下一篇

猜你喜欢

热点阅读