JavaScript继承解析

栏目: JavaScript · 发布时间: 5年前

内容简介:基本上,ES6 的class可以看作只是一个语法糖,它的绝大部分功能,ES5 都可以做到,新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。本篇完。

基本上,ES6 的class可以看作只是一个语法糖,它的绝大部分功能,ES5 都可以做到,新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。

借助构造函数实现继承

  • 缺点:无法继承原型链上的属性和方法
function Person () {
  this.name = 'person1'
}
Person.prototype.sex = '10'
Person.prototype.sayName = function () {
  alert(this.name)
}
function Man () {
  Person.call(this)
  this.age = '24'
}
var m1 = new Man()
console.log(m1) // Man {name: "person1", age: "24"}  (注意:实例自身不存在sex属性和 
sayName方法)
// m1.sayName() // 报错 (因为原型链上也不存在)
复制代码

借助原型链实现继承

  • 缺点:子类共享父类的引用属性
function Father () {
 this.Farr = [1, 2, 3]
}
function Child () { }
Child.prototype = new Father()
var c1 = new Child()
var c2 = new Child()
console.log(c1.Farr) // [1, 2, 3]
console.log(c2.Farr) // [1, 2, 3]
c1.Farr.push(4)
console.log(c1.Farr) // [1, 2, 3, 4]
console.log(c2.Farr) // [1, 2, 3, 4]
复制代码

组合继承

  • 优点:子类不会共享父类中的属性,缺点:Mother构造函数被执行两次,无法确定实例直接父类了
function Mother () {
  console.log('init Mother...')
  this.Marr = ['a', 'b', 'c']
}
function Daughter () {
  Mother.call(this) // 执行一次Mother构造函数
}
Daughter.prototype = new Mother() // 再执行一次Mother构造函数
var d1 = new Daughter()
var d2 = new Daughter()
console.log(d1.Marr) //  ["a", "b", "c"]
console.log(d2.Marr) //  ["a", "b", "c"]
d1.Marr.push('d')
console.log(d1.Marr) // ["a", "b", "c", "d"]
console.log(d2.Marr) //  ["a", "b", "c"]
console.log(d2.__proto__.constructor === Mother) // true(期望值是false,因为Daughter才是d2的直接父类)
复制代码

组合继承优化(一)

  • 优点:防止调用两次构造函数,缺点:依旧无法确定实例直接父类
function Animal () {
  console.log('init Animal...')
}
function Cat () {
  Animal.call(this) // 执行一次Animal构造函数
}
Cat.prototype = Animal.prototype
var cat = new Cat()
console.log(cat.__proto__.constructor === Animal) // true(期望值是false,因为Cat才是cat的直接父类)
复制代码

组合继承优化(二)

  • 解决无法确定实例直接父类问题
function God () {
  console.log('init Final...')
  this.name = 'god'
}
God.prototype.todo = function () {
  alert('todo')
}
function Son () {
  God.call(this)
}
// Son.prototype = God.prototype
Son.prototype = Object.create(God.prototype) // Object.create()方法创建一个新对象,使用现有的对象来提供新创建的对象的__proto__
console.log(God.prototype)
console.log(Object.create(God.prototype))
Son.prototype.constructor = Son

var s = new Son // 无参数时,小括号可以省略
console.log(s)
console.log(s.__proto__.constructor === Son) // true (与期望值一直,完美!)
console.log(s.__proto__.constructor) // true (与期望值一直,完美!)
复制代码

为什么要用Object.create()方法

  • Object.create()方法创建一个新对象,使用现有的对象来提供新创建的对象的__proto__
  • 使用这个方法,传入null可以创建一个无任何属性的对象(原型上也没有)
  • 使用这个方法,会将现有对象放到__proto__属性中,会隐藏现有对象原型上的默认属性和方法,仅仅保留用户自己定义的。
// 普通方法创建对象的对象
console.log({})
// 使用Object.create创建的对象
console.log(Object.create(null))

// 使用Object.create,会将现有对象放到__proto__属性中
function God () {
  console.log('init Final...')
  this.name = 'god'
}
God.prototype.todo = function () {
  alert('todo')
}
function Son () {
  God.call(this)
}
// Son.prototype = God.prototype
Son.prototype = Object.create(God.prototype)
Son.prototype.constructor = Son

console.log(Son.prototype)
复制代码
  • 普通方法创建对象的对象

    JavaScript继承解析
  • 使用Object.create创建的对象

    JavaScript继承解析
  • 使用Object.create()方法实现继承

    JavaScript继承解析
  • 不使用Object.create()方法实现继承

    JavaScript继承解析

本篇完。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Spark

Spark

Bill Chambers、Matei Zaharia / O′Reilly / 2017-10-31 / GBP 39.99

Learn how to use, deploy, and maintain Apache Spark with this comprehensive guide, written by the creators of the open-source cluster-computing framework. With an emphasis on improvements and new feat......一起来看看 《Spark》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具