JavaScript深切之继续的多种体式格局和优缺点

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的值并未发作转变,并不是由于person1person2有自力的 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深切之从原型到原型链》

《JavaScript深切之call和apply的模仿完成》

《JavaScript深切之new的模仿完成》

《JavaScript深切之建立对象》

深切系列

JavaScript深切系列目次地点:https://github.com/mqyqingfeng/Blog

JavaScript深切系列估计写十五篇摆布,旨在帮人人捋顺JavaScript底层学问,重点解说如原型、作用域、实行上下文、变量对象、this、闭包、按值通报、call、apply、bind、new、继续等难点观点。

假如有毛病或许不严谨的处所,请务必赋予斧正,非常谢谢。假如喜好或许有所启示,迎接star,对作者也是一种勉励。

    原文作者:冴羽
    原文地址: https://segmentfault.com/a/1190000009389979
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞