继承
核心;实例父对象属性方法继承(复制) 原型链方法属性的继承(修改原型对象 且 constructor指向子对象)
构造器方式
本质上:创建子类实例调用父对象的构造函数 相当于子实例都会将父对象的属性复制一边(没有需改子对象的原型对象
缺点:
只能继承父对象的本身的方法和属性 不继承原型链上属性和方法
相对来说 无法实现复用 影响性能
/* 父对象 */
function parent() {
this.name = 'chuguo',
this.arr = [1, 2, 3]
}
parent.prototype.getName = function () {
return this.name
}
/* 子对象 */
function child() {
this.test = 'test'
/* 复制父对象方法和属性 */
parent.call(this)
}
child.prototype.getTest = function () {
return this.test
}
const child1 = new child()
const child2 = new child()
console.log(child1.arr, child2.arr)//[ 1, 2, 3 ] [ 1, 2, 3 ]
child1.arr.push(4)
console.log(child1.arr, child2.arr)//[ 1, 2, 3, 4 ] [ 1, 2, 3 ]
console.log(child1.getTest())// test
console.log(child1.getName())// 报错
原型继承方式
本质上:修改原型对象 代替是一个新类型的实例
缺点:
在原型链上查找新的方法或属性时,对父对象的属性(引用类型)上的修改会影响到所有子对象实例
/* 父对象 */
function parent() {
this.name = 'chuguo',
this.arr = [1, 2, 3]
}
parent.prototype.getName = function () {
return this.name
}
/* 子对象 */
function child() {
this.test = 'test'
}
/* 修改原型对象为父对象的实例 */
child.prototype = new parent()
child.prototype.getTest = function () {
return this.test
}
const child1 = new child()
const child2 = new child()
console.log(child1.arr, child2.arr)//[ 1, 2, 3 ] [ 1, 2, 3 ]
/* 修改父对象的引用类型属性 */
child1.arr.push(4)
console.log(child1.arr, child2.arr)//[ 1, 2, 3, 4 ] [ 1, 2, 3, 4 ]
组合继承方式
本质上:对于原型链的方法和属性 采用原型链继承 对于实例属性采用构造器继承
缺点:
原型上存在两根相同的属性方法
对于祖对象的引用类型上会影响所有子实例的访问(尽量实现单继承 类似于Java)
/* 父对象 */
function parent() {
;(this.name = 'chuguo'), (this.arr = [1, 2, 3])
}
parent.prototype.getName = function () {
return this.name
}
parent.prototype.ans = [4, 3, 2]
/* 子对象 */
function child() {
/* 复制父对象方法和属性 最好设置在第一行 便于子对象重写相应的方法属性*/
parent.call(this)
this.test = 'test'
this.name = 'test'
}
child.prototype = new parent()
/* 重写构造器 指向child自己的构造器 */
child.prototype.constructor = child
child.prototype.getTest = function () {
return this.test
}
const child1 = new child()
const child2 = new child()
console.log(child1.arr, child2.arr) //[ 1, 2, 3 ] [ 1, 2, 3 ]
child1.arr.push(4)
console.log(child1.arr, child2.arr) //[ 1, 2, 3, 4 ] [ 1, 2, 3 ]
/* 祖对象的方法属性修改与访问 */
console.log(child1.ans, child2.ans) //[ 4, 3, 2 ] [ 4, 3, 2 ]
child1.ans.push(1)
console.log(child1.ans, child2.ans) //[ 4, 3, 2, 1 ] [ 4, 3, 2, 1 ]
寄生式继承方式
核心:在原型对象基础上 增强对象 返回构造函数
缺点:父对象的引用类型的共享修改
寄生组合式继承方式
function inheritPrototype(subType, superType){
var prototype = Object.create(superType.prototype); // 创建对象,创建父类原型的一个副本
prototype.constructor = subType; // 增强对象,弥补因重写原型而失去的默认的constructor 属性
subType.prototype = prototype; // 指定对象,将新创建的对象赋值给子类的原型
}
/*
代替:
child.prototype = new parent()
child.prototype.constructor = child
*/
ES6方式
exrends核心代码
function _inherits(subType, superType) {
// 创建对象,创建父类原型的一个副本
// 增强对象,弥补因重写原型而失去的默认的constructor 属性
// 指定对象,将新创建的对象赋值给子类的原型
subType.prototype = Object.create(superType && superType.prototype, {
constructor: {
value: subType,
enumerable: false,
writable: true,
configurable: true
}
});
if (superType) {
Object.setPrototypeOf
? Object.setPrototypeOf(subType, superType)
: subType.__proto__ = superType;
}
}
\