原型链的续篇来了,如果不是太了解原型链朋友,可以先看下我的这篇博客,相信你会有所收获的~
构造继承
构造函数绑定
function Animal(){
this.species = '动物';
}
Animal.prototype.eat=function(){
console.log('我是动物')
}
function Cat(name,color){
Animal.call(this,arguments)
this.name = name;
this.color = color;
}
缺点:
- 无法继承原型的方法和属性
- 每生成一个实例,就新开辟一块空间,浪费内存
prototype模式
function Animal(){
this.species = ['动物'];
}
Animal.prototype.eat=function(){
console.log('我是动物')
}
function Cat(name,color){
this.name = name;
this.color = color;
}
Cat.prototype = new Animal();
Cat.prototype.constructor = Cat;
缺点:
- 实例共享同一个原型对象,如果父类是属性是引用类型,如上的
species
,则一个实例修改,那么另外一个也会改变,后续会演示~ - 实例无法向父类构造函数传参
组合模式
function Animal(){
this.species = '动物';
}
Animal.prototype.eat=function(){
console.log('我是动物')
}
function Cat(name,color){
Animal.call(this,arguments)
this.name = name;
this.color = color;
}
Cat.prototype = Animal.prototype;
Cat.prototype.constructor = Cat;
缺点:
- Cat.prototype和Animal.prototype现在指向了同一个对象,那么任何对Cat.prototype的修改,都会反映到Animal.prototype
利用空对象作为中介
解决组合继承出现的问题
function Animal(){
this.species = ['动物'];
}
Animal.prototype.eat=function(){
console.log('我是动物')
}
function Cat(name,color){
Animal.call(this,arguments)
this.name = name;
this.color = color;
}
function extend(Child, Parent) {
var F = function(){};
F.prototype = Parent.prototype;
Child.prototype = new F();
Child.prototype.constructor = Child;
}
extend(Cat, Animal);
截止目前,prototype模式
,组合模式
,利用空对象作为中介
,都有一个问题,那就是父类的原型属性如果是一个引用类型
的话,一个实例改变其属性,其他实例的该属性均发生改变。比如Animal
有一个type属性
Animal.prototype.type = ['哺乳动物']
不管你用这三种的哪一种,去生成两个实例
var cat = new Cat('小莉', '红色')
var cat1 = new Cat('大毛', '黄色');
console.log(cat.type); // ["哺乳动物"]
console.log(cat.type); // ["哺乳动物"]
cat.type.push('肉食动物');
console.log(cat.type); // ["哺乳动物", "肉食动物"]
console.log(cat1.type) // ["哺乳动物", "肉食动物"]
所以呢,prototype
的属性尽量保持都是不变的变量~
非构造继承
Object继承
function CreateObj(o){
function F(){}; // 创建一个构造函数F
F.prototype = o;
return new F();
}
以上也是Object.create的原理,可以直接用Object.create
var info = {
name: "hty",
sex: 18
}
var newInfo = CreateObj(info)
浅拷贝
function extendCopy(p) {
var c = {};
for (var i in p) {
c[i] = p[i];
}
return c;
}
深拷贝
function deepCopy(obj = {}) {
if (typeof obj !=="object" || obj == null) {
return obj
}
let result;
if(obj instanceof Array) {
result = []
} else {
result = {}
}
for(let key in obj) {
result[key] = deepCopy(obj[key])
}
return result
}
ES6继承
class Animals {
constructor(name){
this.name = name
}
getName() {
console.log(this.name)
}
}
class Cat extends Animals {
constructor(name){
super(name)
}
}
let cat = new Cat("小狗")
详细讲解,推荐大家去看阮老师的ES6