We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
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
构造函数、原型和实例之间的关系:每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个原型函数的指针
function Parent() { this.name = 'carpe' } Parent.prototype.getName = function() { return this.name } function Son() { this.age = '18' } // 将构造函数Son的原型挂载到 Parent的实例上 Son.prototype = new Parent() Son.prototype.getAge = function() { return this.age } let son1 = new Son() console.log(son1.name) // carpe console.log(son1.age) // 18 console.log(son1.getName()) // carpe console.log(son1.getAgee()) // 18
缺点: 多个实例对引用数据类型的操作会被篡改
function Parent() { this.colors = ['red', 'yellow', 'black'] } Parent.prototype.getColors = function() { return this.colors } function Son() {} Son.prototype = new Parent() let son1 = new Son() let son2 = new Son() son1.colors.push('blue') console.log(son1.colors) // ['red', 'yellow', 'black', 'blue'] console.log(son2.colors) // ['red', 'yellow', 'black', 'blue']
使用父类的构造函数来增强子类实例,等同于复制父类的实例给子类(不使用原型)
function Parent() { this.numbers = [1,2,3,4,5] } function Son() { Parent.call(this) } let son1 = new Son() let son2 = new Son() son1.numbers.push(6) // [1,2,3,4,5,6] son2.numbers.unshift(0) // [0,1,2,3,4,5]
核心就是Parent.call(this), 创建子类实例时调用Parent构造函数,于是Son的每个实例就会将Parent中的属性复制一份
核心就是Parent.call(this)
Parent
Son
缺点:
就是将原型链继承和借用构造函数继承方式结合, 使用原型链继承的方式对原型实行继承,用借用构造函数实现实例属性继承
function Parent(name) { this.name = name this.numbers = [1,2,3,4,5] } Parent.prototype.sayName = function() { console.log(this.name) } function Son(name, age) { // 借用构造函数继承 Parent.call(this, name) this.age = age } Son.prototype.sayAge = function() { console.log(this.age) } // 原型链继承 Son.prototype = new Parent() // 此时Son的constructor指向Parent, 需要指向Son Son.prototype.constructor = Son let son1 = new Son('carpe', 18) let son2 = new Son('hanzo', 26) son1.numbers.push(6) son1.age = 19 son1.sayName() console.log('son1', son1) console.log('son2', son2)
缺点
numbers
name
son1
son2
age
Son.prototype
利用一个空对象作为中介,将某个对象直接赋值给空对象构造函数的原型
function object(obj) { function fn() {} fn.prototype = obj return new fn() } let person = { name: 'carpe', numbers: [1,2,3,4,5] } let p1 = object(person) let p2 = object(person) p1.name = 'diem' p1.numbers.push(6) p1.numbers.unshift(0) console.log('p1', p1) console.log('p2', p2) console.log('person', person)
ES5中存在Object.create()的方法,能够代替上面的object方法
Object.create()
在原型式继承的基础上,增强对象,返回构造函数
function object(obj) { function fn() {} fn.prototype = obj return new fn() } function createAnother(original) { let clone = object(original) // 通过调用 object() 函数创建一个新对象 clone.sayHi = function() { // 以某种方式来增强对象 alert("hi"); } return clone // 返回这个对象 } let person = { name: 'carpe', numbers: [1, 2, 3, 4, 5] } let p1 = createAhother(person) let p2 = createAhother(person) p1.name = 'diem' p1.numbers.push(6) p1.numbers.unshift(0) console.log('p1', p1) console.log('p2', p2) console.log('person', person)
缺点 和 原型式继承 一样
借用构造函数传递参数和寄生模式实现继承
function object(obj) { function fn() {} fn.prototype = obj return new fn() } function inheritPrototype(son, parent) { let clonePrototype = Object.create(parent.prototype) // 1. 寄生复制一份父类的原型 son.prototype = clonePrototype // 2. 将clonePrototype原型挂到子类的原型上 // 此时的son的原型上的构造函数是clonePrototype的构造函数,也就是parent son.prototype.constructor = son // 3. 手动强制更改son的构造函数 } function Parent(name) { this.name = name this.numbers = [1,2,3,4,5] } Parent.prototype.sayName = function() { console.log(this.name) } function Son(name, age) { // 借用构造函数继承 Parent.call(this, name) this.age = age } inheritPrototype(Son, Parent) Son.prototype.sayAge = function() { console.log(this.age) } let son1 = new Son('carpe', 18) let son2 = new Son('hanzo', 23) son1.numbers.push(6) son1.sayName() son2.numbers.unshift(0) son2.sayName() console.log(son1) console.log(son2)
instanceof
isPrototypeOf()
这是最成熟的方法,也是现在库实现的方法
class Parent { constructor(name) { this.name = name } sayName() { console.log(this.name) } } let p1 = new Parent('carpe') class Son extends Parent { constructor(name, age) { // 在 子类里 必须要调用super super(name) this.age = age } sayAge() { console.log(this.age) } } let son1 = new Son('hanzo', 35) let son2 = new Son('genji', 31) son1.numbers.push(6) son2.numbers.unshift(0) console.log('son1', son1) console.log('son2', son2)
function MyClass() { SuperClass.call(this); OtherSuperClass.call(this); } // 继承一个类 MyClass.prototype = Object.create(SuperClass.prototype); // 混合其它 Object.assign(MyClass.prototype, OtherSuperClass.prototype); // 重新指定constructor MyClass.prototype.constructor = MyClass; MyClass.prototype.myMethod = function() { // do something };
Object.assign会把 OtherSuperClass原型上的函数拷贝到 MyClass原型上,使 MyClass 的所有实例都可用 OtherSuperClass 的方法。
Object.assign
OtherSuperClass
MyClass
The text was updated successfully, but these errors were encountered:
No branches or pull requests
js继承的八种方法
原型链继承
缺点: 多个实例对引用数据类型的操作会被篡改
借用构造函数继承
使用父类的构造函数来增强子类实例,等同于复制父类的实例给子类(不使用原型)
核心就是Parent.call(this)
, 创建子类实例时调用Parent
构造函数,于是Son
的每个实例就会将Parent
中的属性复制一份缺点:
组合继承
就是将原型链继承和借用构造函数继承方式结合, 使用原型链继承的方式对原型实行继承,用借用构造函数实现实例属性继承
缺点
Parent
会给Son
原型对象写入numbers
和name
属性Son
实例的时候,给son1
和son2
写入name
和age
属性son1
上的两个属性就屏蔽了其原型对象Son.prototype
的两个同名属性原型式继承
利用一个空对象作为中介,将某个对象直接赋值给空对象构造函数的原型
缺点:
ES5中存在
Object.create()
的方法,能够代替上面的object方法寄生式继承
在原型式继承的基础上,增强对象,返回构造函数
缺点 和 原型式继承 一样
寄生组合式继承
借用构造函数传递参数和寄生模式实现继承
要点
Parent
构造函数,并且因此避免了在Son.prototype
上创建不必要的、多余的属性。instanceof
和isPrototypeOf()
这是最成熟的方法,也是现在库实现的方法
ES6类继承extends
混入方式继承多个对象(只做了解)
Object.assign
会把OtherSuperClass
原型上的函数拷贝到MyClass
原型上,使 MyClass 的所有实例都可用 OtherSuperClass 的方法。The text was updated successfully, but these errors were encountered: