CodeSky 代码之空

随手记录自己的学习过程

Javascript 好用的prototype以及各种模式介绍

2014-07-23 11:38分类: JavaScript评论: 0

最初创建对象的时候基本上就是这样子的:

1var people = {
2    name: "Nicholas",
3    age: 29,
4    job: "Software Engineer",
5    
6    sayName: function() {
7        console.log(this.name)
8    }
9};
10

后来引入了构造函数模式,差不多就变成了

1function Person(name, age, job) {
2    this.name = name;
3    this.age = age;
4    this.job = job;
5    this.sayName = function() {
6        console.log(this.name);
7    }
8}
9
10var person1 = new Person("Nicholas", 29, "Software Engineer");
11

基本上,这才是我们常见的面向对象模式。

但之后又多了一个原型模式,用prototype来达到效果,他的优点是可以让所有对象实例共享它所包含的属性和方法。

1function Person() {
2}
3
4Person.prototype.name = "Nicholas";
5Person.prototype.sayName = function() {
6    console.log(this.name);
7};
8var person1 = new Person();
9

当然,之后又出现了更简易的语法。

function Person() {
}

Person.prototype = {
    // constructor: Person,
    name: "Nicholas",
    age: 29,
    job: "Software Engineer",
    sayName: function() {
        console.log(this.name);
    }
}

但此时,与上面不同的是,constructor不再指向Person函数,而是指向了Object,我们可以通过注释掉的那句constructor: Person来明确指向,重新指回Person。

感觉上去,使用prototype就是修改起来更加方便,而方便起来真的是挺吓人的,这里有个很明确的例子:

1String.prototype.startsWith = function (text) {
2    return this.indexOf(text) == 0;
3}
4
5var msg = "Hello World";
6console.log(msg.startsWith("Hello"));
7

String是原生引用类型的一个(包括Object、Array、String等),都能自定义方法,或者通过typeof Array.prototype.sort检测方法等,体现出了prototype的强大。 但是不推荐修改原生对象的原型,以免命名冲突等情况

当然prototype也有其缺点:

1function Person() {
2}
3
4Person.prototype = {
5    constructor: Person,
6    name: "Nicholas",
7    age: 29,
8    job: "Software Engineer",
9    friends: ["Shelby", "Count"],
10    sayName: function() {
11        console.log(this.name);
12    }
13}
14
15var person1 = new Person();
16var person2 = new Person();
17
18person1.friends.push("Van");
19
20console.log(person1.friends);
21console.log(person2.friends);
22console.log(person1.friends == person2.friends);
23

比如这段,运行结果为:

[ 'Shelby', 'Count', 'Van' ]
[ 'Shelby', 'Count', 'Van' ]
true

换言之,这就是共享的缺点,大家都同样的会变化,因此也不是最优秀的模式,最终定稿的模式是组合使用构造函数模式和原型模式: 前者用于需要定义的实例属性,后者用于需要共享的实例属性,这样极大程度的节省了内存。

修改成这样:

1function Person(name, age, job) {
2    this.name = name;
3    this.age = age;
4    this.job = job;
5    this.friends = ["Shelby", "Court"];
6}
7
8Person.prototype = {
9    constructor: Person,
10    sayName: function() {
11        console.log(this.name);
12    }
13}
14
15var person1 = new Person("Nicholas", 29, "Software Engineer");
16var person2 = new Person("Greg", 27, "Doctor");
17
18person1.friends.push("Van");
19
20console.log(person1.friends);
21console.log(person2.friends);
22console.log(person1.friends == person2.friends);
23

输出为:

[ 'Shelby', 'Court', 'Van' ]
[ 'Shelby', 'Court' ]
false

评论 (0)