Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JavaScript之面向对象 #6

Open
chenyong9528 opened this issue Jul 29, 2020 · 0 comments
Open

JavaScript之面向对象 #6

chenyong9528 opened this issue Jul 29, 2020 · 0 comments

Comments

@chenyong9528
Copy link
Owner

chenyong9528 commented Jul 29, 2020

面向对象

《JavaScript高级程序设计》笔记

创建对象的方式

1. 工厂模式

function createPerson(name, age, job) {
  var o = new Object()
  o.name = name
  o.age = age
  o.job = job
  o.sayName = function() {
    alert(this.name)
  }
  return o
}

var person = createPerson("faker", 18, "LOL")

缺点:对象无法识别,方法不能共享

2. 构造函数模式

function Person(name, age, job) {
  this.name = name
  this.age = age
  this.job = job
  this.sayName = function() {
    alert(this.name)
  }
}

var person = new Person("faker", 18, "LOL")

缺点:还是方法共享问题

2.1 构造函数模式优化

function Person(name, age, job) {
  this.name = name
  this.age = age
  this.job = job
  this.sayName = sayName
}

function sayName() {
  alert(this.name)
}

var person = new Person("faker", 18, "LOL")

缺点:方法共享了,但谈不上封装,每增加一个方法就得在外面再定义一个函数

3. 原型模式

function Person() {}
Person.prototype = {
  constructor: Person, // 重写原型对象会切断原型与构造函数之间的联系,我们应该纠正它
  name: "faker",
  age: 18,
  job: "LOL",
  sayName() {
    alert(this.name)
  },
}

var person = new Person()

缺点:实例只有共享属性和方法,没有自身的属性,这还不是它最大的问题,最大的问题是它共享本质所导致的;例如,在原型中存在一个引用类型的数组,那么所有实例都会共享该数组,通过实例操作数组会在所有实例中反映出来。

4. 组合模式

function Person(name, age, job) {
  this.name = name
  this.age = age
  this.job = job
}

Person.prototype = {
  constructor: Person,
  sayName() {
    alert(this.name)
  },
}

var person = new Person("faker", 18, "LOL")

集构造函数和原型模式二者之长,这是JavaScript中用的最常用的一种模式

5. 动态原型模式

function Person(name, age, job) {
  this.name = name
  this.age = age
  this.job = job
  if (typeof this.sayName != "function") {
    Person.prototype.sayName = function() {
      alert(this.name)
    }
  }
}

var person = new Person("faker", 18, "LOL")

具有更好的封装性

6. 寄生构造函数模式

function Person(name, age, job) {
  var o = new Object()
  o.name = name
  o.age = age
  o.job =job
  o.sayNmae = function() {
    alert(this.name)
  }
  return o
}

var person = new Person("faker", 18, "LOL")

不太了解有什么用

7. 稳妥构造函数模式

function Person(name) {
  var o = new Object()
  o.sayName = function() {
    alert(name)
  }

  return o
}

var person = Person("faker")

在某些安全环境中会用到这种模式,因为只有sayName方法可以访问到name,它有两个特点:

  1. 不使用this
  2. 不使用new创建对象

仔细看看,其实这是闭包的一种应用

继承的方式

1. 原型链

function SuperType() {
  this.name = "faker"
}

SuperType.prototype.getName = function() {
  return this.name
}

function SubType() {
  
}

// 继承了SuperType
SubType.prototype = new SuperType()
SubType.prototype.constructor = SubType

var instance = new SubType()

alert(instance.getName()) // faker

缺点:

  1. 包含引用类型的值会被所有实例共享(原型不就是用来共享的?)
  2. 子类原型成为了父类的一个实例,父类实例中的属性也变成了原型中的属性(我们想要的是一个纯净的原型)

2. 借用构造函数

function SuperType(name){
  this.name = name
}

function SubType(name){  
  SuperType.call(this, name)
}

var instance = new SubType("faker")
alert(instance.name)   // faker

缺点:仅使用借用构造函数无法避免构造函数存在的共享问题

3. 组合继承

function SuperType(name) {
  this.name = name
}

SuperType.prototype.getName= function() {
  return this.name
}

function SubType(name) {
  // 继承了属性
  SuperType.call(this, name)
}

// 继承了方法
SubType.prototype = new SuperType()
SubType.prototype.constructor = SubType

var instance = new SubType("faker")
alert(instance.getName()) // faker

缺点:虽然集原型链和构造函数二者之长,但有两个问题:

  1. 调用了两次父构造函数
  2. 实例的name会屏蔽掉SubType原型中的name,其实原型中的name的存在是没有意义的

4. 原型式继承

function object(o) {
  function F() {}
  F.ptototype = o
  return new F()
}
var o = {
  name: "faker"
}
var obj = object(o)
alert(obj.name) // faker

// 更好的方式
var obj1 = Object.create(o)
alert(obj1.name) // faker

这是道格拉斯提出的一种,以现有对象为原型来创建新对象的方式,ES5中用Object.create()规范了这种方式

5. 寄生式继承

function createAnother(o) {
  var clone = Object.create(o)
  clone.sayHi = function() { // 增强对象
    alert("Hi!")
  }
  return clone
}

顾名思义,这是一种寄生在原型式继承之上的一种模式

6. 寄生组合式继承

function inheritPrototype(subType, superType) {
  var prototype = Object.create(superType.prototype)
  prototype.constructor = subType
  subType.prototype = prototype
}

function SuperType(name) {
  this.name = name
}

SuperType.prototype.getName = function() {
  return this.name
}

function SubType(name, age) {
  SuperType.call(this, name)
  this.age = age
}

inheritPrototype(SubType, SuperType)

var instance = new SubType("faker", 18)
alert(instance.getName()) // faker

寄生组合式继承是寄生式继承和借用构造函数的组合,相比组合继承,它只调用了一次父构造函数,因此在子类的原型上也没有了多余的属性。这是目前最理想的继承范式。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant