JavaScript深切之建立对象的多种体式格局以及优缺点

JavaScript深切系列第十四篇,解说建立对象的各种体式格局,以及优瑕玷。

写在前面

这篇文章解说建立对象的各种体式格局,以及优瑕玷。

然则注重:

这篇文章更像是笔记,由于《JavaScript高等程序设计》写得真是太好了!

1. 工场形式

function createPerson(name) {
    var o = new Object();
    o.name = name;
    o.getName = function () {
        console.log(this.name);
    };

    return o;
}

var person1 = createPerson('kevin');

瑕玷:对象没法辨认,由于一切的实例都指向一个原型

2. 组织函数形式

function Person(name) {
    this.name = name;
    this.getName = function () {
        console.log(this.name);
    };
}

var person1 = new Person('kevin');

长处:实例能够辨认为一个特定的范例

瑕玷:每次建立实例时,每一个要领都要被建立一次

2.1 组织函数形式优化

function Person(name) {
    this.name = name;
    this.getName = getName;
}

function getName() {
    console.log(this.name);
}

var person1 = new Person('kevin');

长处:处理了每一个要领都要被从新建立的题目

瑕玷:这叫啥封装……

3. 原型形式

function Person(name) {

}

Person.prototype.name = 'keivn';
Person.prototype.getName = function () {
    console.log(this.name);
};

var person1 = new Person();

长处:要领不会从新建立

瑕玷:1. 一切的属性和要领都同享 2. 不能初始化参数

3.1 原型形式优化

function Person(name) {

}

Person.prototype = {
    name: 'kevin',
    getName: function () {
        console.log(this.name);
    }
};

var person1 = new Person();

长处:封装性好了一点

瑕玷:重写了原型,丧失了constructor属性

3.2 原型形式优化

function Person(name) {

}

Person.prototype = {
    constructor: Person,
    name: 'kevin',
    getName: function () {
        console.log(this.name);
    }
};

var person1 = new Person();

长处:实例能够经由历程constructor属性找到所属组织函数

瑕玷:原型形式该有的瑕玷照样有

4. 组合形式

组织函数形式与原型形式双剑合璧。

function Person(name) {
    this.name = name;
}

Person.prototype = {
    constructor: Person,
    getName: function () {
        console.log(this.name);
    }
};

var person1 = new Person();

长处:该同享的同享,该私有的私有,运用最普遍的体式格局

瑕玷:有的人就是愿望全部都写在一同,即更好的封装性

4.1 动态原型形式

function Person(name) {
    this.name = name;
    if (typeof this.getName != "function") {
        Person.prototype.getName = function () {
            console.log(this.name);
        }
    }
}

var person1 = new Person();

注重:运用动态原型形式时,不能用对象字面量重写原型

诠释下为什么:

function Person(name) {
    this.name = name;
    if (typeof this.getName != "function") {
        Person.prototype = {
            constructor: Person,
            getName: function () {
                console.log(this.name);
            }
        }
    }
}

var person1 = new Person('kevin');
var person2 = new Person('daisy');

// 报错 并没有该要领
person1.getName();

// 解释掉上面的代码,这句是能够实行的。
person2.getName();

为了诠释这个题目,假定最先实行var person1 = new Person('kevin')

假如对 new 和 apply 的底层实行历程不是很熟悉,能够浏览底部相干链接中的文章。

我们回忆下 new 的完成步骤:

  1. 起首新建一个对象

  2. 然后将对象的原型指向 Person.prototype

  3. 然后 Person.apply(obj)

  4. 返回这个对象

注重这个时刻,回忆下 apply 的完成步骤,会实行 obj.Person 要领,这个时刻就会实行 if 语句里的内容,注重组织函数的 prototype 属性指向了实例的原型,运用字面量体式格局直接掩盖 Person.prototype,并不会变动实例的原型的值,person1 依然是指向了之前的原型,而不是 Person.prototype。而之前的原型是没有 getName 要领的,所以就报错了!

假如你就是想用字面量体式格局写代码,能够尝试下这类:

function Person(name) {
    this.name = name;
    if (typeof this.getName != "function") {
        Person.prototype = {
            constructor: Person,
            getName: function () {
                console.log(this.name);
            }
        }

        return new Person(name);
    }
}

var person1 = new Person('kevin');
var person2 = new Person('daisy');

person1.getName(); // kevin
person2.getName();  // daisy

5.1 寄生组织函数形式

function Person(name) {

    var o = new Object();
    o.name = name;
    o.getName = function () {
        console.log(this.name);
    };

    return o;

}

var person1 = new Person('kevin');
console.log(person1 instanceof Person) // false
console.log(person1 instanceof Object)  // true

寄生组织函数形式,我个人认为应当如许读:

寄生-组织函数-形式,也就是说寄生在组织函数的一种要领。

也就是说打着组织函数的幌子挂羊头卖狗肉,你看建立的实例运用 instanceof 都没法指向组织函数!

如许要领能够在特别情况下运用。比方我们想建立一个具有分外要领的特别数组,然则又不想直接修正Array组织函数,我们能够如许写:

function SpecialArray() {
    var values = new Array();

    for (var i = 0, len = arguments.length; i < len; i++) {
        values.push(arguments[i]);
    }

    values.toPipedString = function () {
        return this.join("|");
    };
    return values;
}

var colors = new SpecialArray('red', 'blue', 'green');
var colors2 = SpecialArray('red2', 'blue2', 'green2');


console.log(colors);
console.log(colors.toPipedString()); // red|blue|green

console.log(colors2);
console.log(colors2.toPipedString()); // red2|blue2|green2

你会发明,实在所谓的寄生组织函数形式就是比工场形式在建立对象的时刻,多运用了一个new,实际上二者的结果是一样的。

然则作者多是愿望能像运用一般 Array 一样运用 SpecialArray,虽然把 SpecialArray 当做函数也一样能用,然则这并非作者的本意,也变得不文雅。

在能够运用其他形式的情况下,不要运用这类形式。

然则值得一提的是,上面例子中的轮回:

for (var i = 0, len = arguments.length; i < len; i++) {
    values.push(arguments[i]);
}

能够替换成:

values.push.apply(values, arguments);

5.2 稳妥组织函数形式

function person(name){
    var o = new Object();
    o.sayName = function(){
        console.log(name);
    };
    return o;
}

var person1 = person('kevin');

person1.sayName(); // kevin

person1.name = "daisy";

person1.sayName(); // kevin

console.log(person1.name); // daisy

所谓稳妥对象,指的是没有大众属性,而且其要领也不援用 this 的对象。

与寄生组织函数形式有两点差别:

  1. 新建立的实例要领不援用 this

  2. 不运用 new 操作符挪用组织函数

稳妥对象最适合在一些平安的环境中。

稳妥组织函数形式也跟工场形式一样,没法辨认对象所属范例。

下一篇文章

JavaScript深切之继续的多种体式格局和优瑕玷

相干链接

《JavaScript深切之从原型到原型链》

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

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

深切系列

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

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

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

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