JavaScript深入之创建对象的多种方式以及优缺点,

2019-10-16 15:39 来源:未知

JavaScript 深远之创设对象的有余方法以致优劣点

2017/05/28 · JavaScript · 对象

最初的稿件出处: 冴羽   

源于《JavaScript高端程序设计》

写在后边

那篇小说疏解创设对象的各个艺术,以至优短处。

唯独注意:

那篇小说更疑似笔记,因为《JavaScript高档程序设计》写得真是太好了!

  1. 工厂方式

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');

破绽:对象不能辨识,因为兼具的实例都指向三个原型

function createPerson(name) {

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');

优点:实例能够辨别为八个特定的体系

劣势:每趟成立实例时,每个方法都要被创建一次

    var o = new Object();

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');

优点:消除了种种方法都要被另行创建的标题

短处:那叫什么封装……

    o.name = name;

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. 不可能开端化参数

    o.getName = function () {

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属性

        console.log(this.name);

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();

优点:该共享的分享,该民用的村办,使用最常见的措施

破绽:有的人正是期望任何都写在一同,即越来越好的封装性

    return o;

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);

var person1 = createPerson('kevin');

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浓郁体系目录地址:。

金沙澳门唯一官网,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

  1. 构造函数情势

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. 原型情势

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();

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属性找到所属构造函数

破绽:原型方式该有的症结仍旧有

  1. 构成情势

构造函数方式与原型形式双剑合璧。

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 的贯彻步骤:

先是新建一个对象

接下来将对象的原型指向 Person.prototype

然后 Person.apply(obj)

归来那个指标

瞩目这年,回想下 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 一样接纳 特略Array,就算把 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 的目的。

与寄生构造函数情势有两点区别:

新创设的实例方法不引用 this

不利用 new 操作符调用构造函数

安妥对象最符合在一些安全的情况中。

妥贴构造函数方式也跟工厂情势同样,不可能辨认对象所属类型。

TAG标签:
版权声明:本文由金沙澳门唯一官网发布于前端开发,转载请注明出处:JavaScript深入之创建对象的多种方式以及优缺点,