1.创建对象
1. 构造函数模式
function Person(name) {
this.name = name
this.getName = function () {
console.log(this.name)
}
}
var p = new Person()
2. 原型模式
function Person(name) {
}
Person.prototype.name = 'keivn'
Person.prototype.getName = function () {
console.log(this.name)
}
var p = new Person()
优点: 方法不会重新创建
缺点: 1.所有的属性和方法都共享
2.原型和原型链
2.继承
父类
function Animal (name) {
this.name = name
this.colors = []
}
Animal.prototype.sayName = function() {
console.log(this.name)
}
1. 原型链继承
function Dog () {
this.name = 'Dog'
this.sayName = function() {
console.log('内部 sayName--->', this.name)
}
}
Dog.prototype.sayName = function() {
console.log('prototype -->', this.name)
}
// 继承父类 Dog.prototype.constructor === Animal
Dog.prototype = new Animal()
Dog.prototype.sayName = function () {
console.log('Dog sayName')
}
var d1 = new Dog()
d1.colors.push('red')
var d2 = new Dog()
console.log(d2.colors)
问题:
原型链包含引用值 会在所有的实例间共享
子类有时候需要覆盖父类的方法,或者增加父类没有的方法。为此,这些方法必须在原型赋值之后 再添加到原型上
2.借用构造函数
function Cat () {
Animal.call(this)
// Animal.call(this, 'Bar') 继承父类,并传参
}
let c = new Cat()
console.log(c)
3.组合继承
function Pets(name, age) {
Animal.call(this, name) // 第二次调用Animal
this.age = age
}
Pets.prototype = new Animal() // 第一次调用Animal()
let p = new Pets('pig one', 3)
console.log(p)
组合继承弥补了原型链和盗用构造函数的不足,是JavaScript中使用最多的继承模式。而且组合继承也保留了instanceof
操作符和isPrototypeOf()
方法识别合成对象的能力
4.原型式继承
ECMAScript 5通过增加Object.create()
方法将原型式继承的概念规范化了。
function object(o) {
function F() {}
F.prototype = o
return new F()
}
let person = {
name: 'Greg'
}
let anotherPerson = object(person)
5. 寄生式继承
通过调用函数创建一个新对象
function create(argument) {
let clone = object(original)
clone.sayHi = function() { // 以某种方式增强这个对象
console.log('hi')
}
return clone
}
let person = {
name: 'Greg'
}
let anotherPerson = createAnother(person)
anotherPerson.sayHi() // 'hi'
6.寄生式组合继承
function inheritPrototype(dog, animal) {
let prototype = object.create(Animal.prototype)
prototype.constructor = dog
dog.prototype = prototype
}
function Dog(name, age) {
Animal.call(this, name)
}
inheritPrototype(Dog, Animal)
var d = new Dog()
d.sayName()
- 原型式继承可以无须明确定义构造函数而实现继承,本质上是对给定对象执行浅复制。这种操作的结果之后还可以再进一步增强。
- 与原型式继承紧密相关的是寄生式继承,即先基于一个对象创建一个新对象,然后再增强这个新对象,最后返回新对象。这个模式也被用在组合继承中,用于避免重复调用父类构造函数导致的浪费。
- 寄生组合继承被认为是实现基于类型继承的最有效方式。
参考链接
深入理解 JavaScript 原型
JavaScript深入之从原型到原型链 #2
JavaScript深入之new的模拟实现
What is the difference between prototype-based class syntax and class syntax in JavaScript?