导读
javascript面向对象编程学习(一)
javascript面向对象编程学习(二) —— 原型链继承
javascript面向对象编程学习(三) —— 构造函数继承和组合继承
一、原型式继承
1. 如何实现原型式继承?
把某一个对象直接赋值给构造函数的原型,或者使用Object.create()
方法。
2.代码实现
2.1 使用构造函数原型实现
function CreateObject(obj){
function O() {};
O.prototype = obj;
return new O();
}
const person = {
name: '大魔王',
names: ['小魔王', '魔鬼']
}
const child = CreateObject(person);
console.log(child.name); // 大魔王
child.name = '小魔王'
child.names.push('魔王')
console.log(child.name); // 小魔王
console.log(child.names); // ["小魔王", "魔鬼", "魔王"]
const child2 = CreateObject(person);
child2.names.push('人类');
console.log(person.names); // ["小魔王", "魔鬼", "魔王", "人类"]
2.2 使用Object.create()
实现。Object.create()
方法创建一个新对象,使用现有的对象来提供新创建的对象的__proto__
。
const person = {
name: '大魔王',
names: ['小魔王', '魔鬼']
}
const child = Object.create(person);
console.log(child.name); // 大魔王
child.name = '小魔王' ;
child.names.push('魔王');
console.log(child.name); // 小魔王
console.log(child.names); // ["小魔王", "魔鬼", "魔王"]
const child2 = Object.create(person);
child2.names.push('人类');
console.log(person.names); // ["小魔王", "魔鬼", "魔王", "人类"]
3. 缺点
- 多个实例的引用类型指向相同,操作其中一个实例的某个引用类型,所有实例中此引用类型都将被修改。
- 无法传递参数,无法实现复用。(实例额外属性都是后面添加的)
二、寄生式继承
创建一个仅用于封装继承过程的函数,该函数在内部以某种形式来做增强对象,最后返回对象
function createObj (o) {
const obj = Object.create(o);
obj.getName = function () {
console.log(obj.name);
}
return obj;
}
const person = {
name: '小魔王'
}
const child = createObj(person);
child.getName(); // 小魔王
三、寄生组合式继承
1.如何实现?
利用构造函数和寄生方式继承属性,利用原型链继承方法。
2.代码实现
/**
*继承函数
*
* @param {*} Child 子构造函数
* @param {*} Parent 父构造函数
*/
function selfExtends(Child, Parent) {
const prototype = Object.create(Parent.prototype); // 复制父构造函数的prototype
prototype.constructor = Child; // 把constructor指向Child
Child.prototype = prototype; // 修改Child的prototype
}
function Person(name) {
this.name = name;
this.friends = ['大魔王', '人类', '魔鬼'];
}
Person.prototype.getName = function () {
console.log(this.name);
}
function Child(name, age) {
Person.call(this, name); // 使用构造函数方式 继承父属性 支持传参
this.age = age;
}
// 继承原型上的属性和方法,实际就是修改原型链
selfExtends(Child, Person);
// 继承后,才能在原型链上写属性和方法,不然会被替换掉
Child.prototype.getAge = function () {
console.log(this.age);
}
const child = new Child('小魔王', 22);
const child2 = new Child('人类', 23);
child.friends.push('魔帝');
child2.friends.push('小魔王');
console.log(child.friends); // ["大魔王", "人类", "魔鬼", "魔帝"]
console.log(child2.friends); // ["大魔王", "人类", "魔鬼", "小魔王"]
child.getName(); // 小魔王
child2.getName(); // 人类
child.getAge(); // 22
child2.getAge(); // 23
总结
有人说,现在直接用es6的class就可以实现继承了,为什么还要去学习es5的继承方式?
如果有这种想法就错了,如果你想成为一个厉害的前端,你必须务实基础。
打好基础,能够帮助自己以后阅读框架源码或者自己写框架走一点小捷径。