JavaScript深切系列第十五篇,解说JavaScript种种继续体式格局和优瑕玷。
写在前面
本文解说JavaScript种种继续体式格局和优瑕玷。
然则注重:
这篇文章更像是笔记,哎,再让我叹息一句:《JavaScript高等程序设计》写得真是太好了!
1.原型链继续
function Parent () {
this.name = 'kevin';
}
Parent.prototype.getName = function () {
console.log(this.name);
}
function Child () {
}
Child.prototype = new Parent();
var child1 = new Child();
console.log(child1.getName()) // kevin
题目:
1.援用范例的属性被一切实例同享,举个例子:
function Parent () {
this.names = ['kevin', 'daisy'];
}
function Child () {
}
Child.prototype = new Parent();
var child1 = new Child();
child1.names.push('yayu');
console.log(child1.names); // ["kevin", "daisy", "yayu"]
var child2 = new Child();
console.log(child2.names); // ["kevin", "daisy", "yayu"]
2.在建立 Child 的实例时,不能向Parent传参
2.借用组织函数(典范继续)
function Parent () {
this.names = ['kevin', 'daisy'];
}
function Child () {
Parent.call(this);
}
var child1 = new Child();
child1.names.push('yayu');
console.log(child1.names); // ["kevin", "daisy", "yayu"]
var child2 = new Child();
console.log(child2.names); // ["kevin", "daisy"]
长处:
1.防止了援用范例的属性被一切实例同享
2.可以在 Child 中向 Parent 传参
举个例子:
function Parent (name) {
this.name = name;
}
function Child (name) {
Parent.call(this, name);
}
var child1 = new Child('kevin');
console.log(child1.name); // kevin
var child2 = new Child('daisy');
console.log(child2.name); // daisy
瑕玷:
要领都在组织函数中定义,每次建立实例都邑建立一遍要领。
3.组合继续
原型链继续和典范继续双剑合璧。
function Parent (name) {
this.name = name;
this.colors = ['red', 'blue', 'green'];
}
Parent.prototype.getName = function () {
console.log(this.name)
}
function Child (name, age) {
Parent.call(this, name);
this.age = age;
}
Child.prototype = new Parent();
var child1 = new Child('kevin', '18');
child1.colors.push('black');
console.log(child1.name); // kevin
console.log(child1.age); // 18
console.log(child1.colors); // ["red", "blue", "green", "black"]
var child2 = new Child('daisy', '20');
console.log(child2.name); // daisy
console.log(child2.age); // 20
console.log(child2.colors); // ["red", "blue", "green"]
长处:融会原型链继续和组织函数的长处,是 JavaScript 中最经常运用的继续情势。
4.原型式继续
function createObj(o) {
function F(){}
F.prototype = o;
return new F();
}
就是 ES5 Object.create 的模仿完成,将传入的对象作为建立的对象的原型。
瑕玷:
包括援用范例的属性值一直都邑同享响应的值,这点跟原型链继续一样。
var person = {
name: 'kevin',
friends: ['daisy', 'kelly']
}
var person1 = createObj(person);
var person2 = createObj(person);
person1.name = 'person1';
console.log(person2.name); // kevin
person1.firends.push('taylor');
console.log(person2.friends); // ["daisy", "kelly", "taylor"]
注重:修正person1.name
的值,person2.name
的值并未发作转变,并不是由于person1
和person2
有自力的 name 值,而是由于person1.name = 'person1'
,给person1
添加了 name 值,并不是修正了原型上的 name 值。
5. 寄生式继续
建立一个仅用于封装继续历程的函数,该函数在内部以某种情势来做加强对象,末了返回对象。
function createObj (o) {
var clone = object.create(o);
clone.sayName = function () {
console.log('hi');
}
return clone;
}
瑕玷:跟借用组织函数情势一样,每次建立对象都邑建立一遍要领。
6. 寄生组合式继续
为了轻易人人浏览,在这里反复一下组合继续的代码:
function Parent (name) {
this.name = name;
this.colors = ['red', 'blue', 'green'];
}
Parent.prototype.getName = function () {
console.log(this.name)
}
function Child (name, age) {
Parent.call(this, name);
this.age = age;
}
Child.prototype = new Parent();
var child1 = new Child('kevin', '18');
console.log(child1)
组合继续最大的瑕玷是会挪用两次父组织函数。
一次是设置子范例实例的原型的时刻:
Child.prototype = new Parent();
一次在建立子范例实例的时刻:
var child1 = new Child('kevin', '18');
追念下 new 的模仿完成,实在在这句中,我们会实行:
Parent.call(this, name);
在这里,我们又会挪用了一次 Parent 组织函数。
所以,在这个例子中,假如我们打印 child1 对象,我们会发明 Child.prototype 和 child1 都有一个属性为colors
,属性值为['red', 'blue', 'green']
。
那末我们该怎样字斟句酌,防止这一次反复挪用呢?
假如我们不运用 Child.prototype = new Parent() ,而是间接的让 Child.prototype 访问到 Parent.prototype 呢?
看看怎样完成:
function Parent (name) {
this.name = name;
this.colors = ['red', 'blue', 'green'];
}
Parent.prototype.getName = function () {
console.log(this.name)
}
function Child (name, age) {
Parent.call(this, name);
this.age = age;
}
// 症结的三步
var F = function () {};
F.prototype = Parent.prototype;
Child.prototype = new F();
var child1 = new Child('kevin', '18');
console.log(child1);
末了我们封装一下这个继续要领:
function object(o) {
function F() {}
F.prototype = o;
return new F();
}
function prototype(child, parent) {
var prototype = object(parent.prototype);
prototype.constructor = child;
child.prototype = prototype;
}
// 当我们运用的时刻:
prototype(Child, Parent);
援用《JavaScript高等程序设计》中对寄生组合式继续的夸奖就是:
这类体式格局的高效率表现它只挪用了一次 Parent 组织函数,而且因而防止了在 Parent.prototype 上面建立不必要的、过剩的属性。与此同时,原型链还能坚持稳定;因而,还可以一般运用 instanceof 和 isPrototypeOf。开发人员普遍认为寄生组合式继续是援用范例最理想的继续范式。
相干链接
《JavaScript深切之call和apply的模仿完成》
深切系列
JavaScript深切系列目次地点:https://github.com/mqyqingfeng/Blog。
JavaScript深切系列估计写十五篇摆布,旨在帮人人捋顺JavaScript底层学问,重点解说如原型、作用域、实行上下文、变量对象、this、闭包、按值通报、call、apply、bind、new、继续等难点观点。
假如有毛病或许不严谨的处所,请务必赋予斧正,非常谢谢。假如喜好或许有所启示,迎接star,对作者也是一种勉励。