C语言网站开发pdf,网站改版后百度不收录,上海市嘉定区建设银行网站,黑龙江建设网网站盗用构造函数
上节提到原型包含引用值导致的继承问题#xff0c;为了解决这种问题#xff0c;一种叫作“盗用构造函数”#xff08;constructor stealing#xff09;的技术在开发社区流行起来#xff08;这种技术有时也称作“对象伪装”或“经典继承”#xff09;。基本…盗用构造函数
上节提到原型包含引用值导致的继承问题为了解决这种问题一种叫作“盗用构造函数”constructor stealing的技术在开发社区流行起来这种技术有时也称作“对象伪装”或“经典继承”。基本思路很简单在子类构造函数中调用父类构造函数。因为毕竟函数就是在特定上下文中执行代码的简单对象所以可以使用apply()和 call()方法以新创建的对象为上下文执行构造函数。来看下面的例子
function SuperType() { this.colors [red, blue, green];
}
function SubType() { // 继承 SuperType SuperType.call(this);
}
let instance1 new SubType();
instance1.colors.push(black);
console.log(instance1.colors); // red,blue,green,black
let instance2 new SubType();
console.log(instance2.colors); // red,blue,green每个实例都会有自己的 colors 属性
传递参数
function SuperType(name){ this.name name;
}
function SubType() { // 继承 SuperType 并传参SuperType.call(this, Nicholas); // 实例属性this.age 29;
}
let instance new SubType();
console.log(instance.name); // Nicholas;
console.log(instance.age); // 29盗用构造函数的问题 盗用构造函数的主要缺点也是使用构造函数模式自定义类型的问题必须在构造函数中定义方法因此函数不能重用。此外子类也不能访问父类原型上定义的方法因此所有类型只能使用构造函数模式。
组合继承
组合继承有时候也叫伪经典继承综合了原型链和盗用构造函数将两者的优点集中了起来。基本的思路是使用原型链继承原型上的属性和方法而通过盗用构造函数继承实例属性。这样既可以把方法定义在原型上以实现重用又可以让每个实例都有自己的属性。来看下面的例子
function SuperType(name){ this.name name; this.colors [red, blue, green];
}
SuperType.prototype.sayName function() { console.log(this.name);
};
function SubType(name, age){ // 继承属性SuperType.call(this, name); this.age age;
}
// 继承方法
SubType.prototype new SuperType();
SubType.prototype.sayAge function() { console.log(this.age);
};
let instance1 new SubType(Nicholas, 29);
instance1.colors.push(black);
console.log(instance1.colors); // red,blue,green,black
instance1.sayName(); // Nicholas;
instance1.sayAge(); // 29
let instance2 new SubType(Greg, 27);
console.log(instance2.colors); // red,blue,green
instance2.sayName(); // Greg;
instance2.sayAge(); // 27组合继承弥补了原型链和盗用构造函数的不足是 JavaScript 中使用最多的继承模式。
原型式继承
2006 年Douglas Crockford 写了一篇文章《JavaScript 中的原型式继承》“Prototypal Inheritance in JavaScript”。这篇文章介绍了一种不涉及严格意义上构造函数的继承方法。他的出发点是即使不自定义类型也可以通过原型实现对象之间的信息共享。文章最终给出了一个函数
function object(o) { function F() {} F.prototype o; return new F();
}本质上object()是对传入的对象执行了一次浅复制。
let person { name: Nicholas, friends: [Shelby, Court, Van]
};
let anotherPerson object(person);
anotherPerson.name Greg;
anotherPerson.friends.push(Rob);
let yetAnotherPerson object(person);
yetAnotherPerson.name Linda;
yetAnotherPerson.friends.push(Barbie);
console.log(person.friends); // Shelby,Court,Van,Rob,BarbieECMAScript 5 通过增加 Object.create()方法将原型式继承的概念规范化了。
let person { name: Nicholas, friends: [Shelby, Court, Van]
};
let anotherPerson Object.create(person);
anotherPerson.name Greg;
anotherPerson.friends.push(Rob);
let yetAnotherPerson Object.create(person);
yetAnotherPerson.name Linda;
yetAnotherPerson.friends.push(Barbie);
console.log(person.friends); // Shelby,Court,Van,Rob,Barbie寄生式继承
寄生式继承parasitic inheritance也是 Crockford 首倡的一种模式
function createAnother(original){ let clone object(original); // 通过调用函数创建一个新对象clone.sayHi function() { // 以某种方式增强这个对象console.log(hi); }; return clone; // 返回这个对象
}
let person { name: Nicholas, friends: [Shelby, Court, Van]
};
let anotherPerson createAnother(person);
anotherPerson.sayHi(); // hi这个例子基于 person 对象返回了一个新对象。新返回的 anotherPerson 对象具有 person 的所有属性和方法还有一个新方法叫 sayHi()。 注意 通过寄生式继承给对象添加函数会导致函数难以重用与构造函数模式类似。
寄生式组合继承
function SuperType(name) { this.name name; this.colors [red, blue, green];
}
SuperType.prototype.sayName function() { console.log(this.name);
};
function SubType(name, age){ SuperType.call(this, name); // 第二次调用 SuperType() this.age age;
}
SubType.prototype new SuperType(); // 第一次调用 SuperType()
SubType.prototype.constructor SubType;
SubType.prototype.sayAge function() { console.log(this.age);
};好了抄完了这几种继承方式了下节抄开始抄类。 又马上清明节了读一首
忆江南·清明六首 其四 清代 陆震 清明节记得在西园。都是桃花都是柳半含朝雨半含烟。人在画图边。