菜单

JavaScript深入之创建对象的多方法和优缺点

2018年11月15日 - JavaScript

JavaScript 深入之创建对象的有余主意与优缺点

2017/05/28 · JavaScript
· 对象

原文出处: 冴羽   

早已离开简书,原因参见
http://www.jianshu.com/p/0f12350a6b66。

写于前方

立马篇稿子讲解创建对象的各种方法,以及优缺点。

可注意:

马上首文章又像是笔记,因为《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’);

1
2
3
4
5
6
7
8
9
10
11
function createPerson(name) {
    var o = new Object();
    o.name = name;
    o.getName = function () {
        console.log(this.name);
    };
 
    return o;
}
 
var person1 = createPerson(‘kevin’);

症结:对象无法甄别,因为具有的实例都针对一个原型

章可于我之 Github
https://github.com/mqyqingfeng/Blog
查看

2. 构造函数模式

function Person(name) { this.name = name; this.getName = function () {
console.log(this.name); }; } var person1 = new Person(‘kevin’);

1
2
3
4
5
6
7
8
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’);

1
2
3
4
5
6
7
8
9
10
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
4
5
6
7
8
9
10
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();

1
2
3
4
5
6
7
8
9
10
11
12
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();

1
2
3
4
5
6
7
8
9
10
11
12
13
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();

1
2
3
4
5
6
7
8
9
10
11
12
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();

1
2
3
4
5
6
7
8
9
10
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();

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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]); }

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

可以轮换成:

values.push.apply(values, arguments);

1
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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深入系列目录地址:https://github.com/mqyqingfeng/Blog。

JavaScript深入系列预计写十五篇左右,旨在救助大家捋顺JavaScript底层知识,重点教学如原型、作用域、执行上下文、变量对象、this、闭包、按值传递、call、apply、bind、new、继承等难点概念。

要是起左或无谨言慎行的地方,请务必与指正,十分谢谢。如果喜欢或者持有启发,欢迎star,对笔者为是均等栽鞭策。

  1. JavaScirpt 深入之从原型到原型链
  2. JavaScript
    深入的词法作用域和动态作用域
  3. JavaScript 深入之履上下文栈
  4. JavaScript 深入的变量对象
  5. JavaScript 深入之图域链
  6. JavaScript 深入的从 ECMAScript 规范解读
    this
  7. JavaScript 深入的履上下文
  8. JavaScript 深入之闭包
  9. JavaScript 深入的参数按值传递
  10. JavaScript
    深入之call和apply的学实现
  11. JavaScript 深入之bind的套实现
  12. JavaScript 深入的new的拟实现
  13. JavaScript 深入之类数组对象和
    arguments

    1 赞 收藏
    评论

图片 1

相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图