菜单

JavaScript深刻之制造对象的三种格局以及优缺点

2019年3月31日 - 金沙前端

写在前头

那篇小说讲解创设对象的种种格局,以及优缺点。

可是注意:

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

为了表明那个标题,假如开端进行var person1 = new Person(‘kevin’)。

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”]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
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 中最常用的接轨格局。

JavaScript成立对象格局计算

//object构造函数
// 优点:简单方便
// 缺点:批量创建对象很麻烦,不能使用instanceof来确定对象类型
var person = new Object();
person.name = "masike";
person.age=19;
person.job="student";
person.sayName=function(){
    console.log(this.name);
};

//字面量
var person = {
    name:"masike",
    age:22,
    job:"student",
    sayName:function(){
        console.log(this.name);
    }
}```
- 工厂模式:简单的函数创建对象,为对象添加属性和方法,然后返回对象,这个模式后来被构造函数所取代。
```JavaScript
//工厂模式
// 优点:减少了代码量
// 缺点:未能解决对象识别问题
function createPerson(name,age,job){
    var o=new Object();
    o.name=name;
    o.age=19;
    o.job="student";
    o.sayName=function(){
        console.log(this.name);
    }
    return o;
}
var person1=createPerson("masike",19,"student");
var person2=createPerson("withershins",20,"worker");```
- 构造函数模式:自定义引用类型,像创建对象实例一样使用new操作符,缺点是每个成员无法得到复用,包括函数。

//构造函数形式
//优点:在工厂格局的功底下消除了指标识别难点
//缺点:每种实例的章程皆以单独的,多数情况下同个指标的实例方法都是同等的
function Person(name,age,job){
this.name=name;
this.age=age;
this.job=job;
this.sayName=function(){
console.log(this.name);
}
}
var person1=new Person(“masike”,19,”student”);
var person2=new Person(“withershins”,19,”worker”);
//偏方
function Person(name,age,job){
this.name=name;
this.age=age;
this.job=job;
this.sayName=sayName;
}
function sayName(){
console.log(this.name);
}
var person1=new Person(“masike”,19,”student”);
var person2=new Person(“withershins”,19,”worker”);“`

//原型模式
//优点:公用原型减少了赘余
//缺点:在原型的改变会影响到所有的实例,于是实例没有了独立性
function Person(){
}
Person.prototype.name="masike";
Person.prototype.age=19;
Person.prototype.job="student";
Person.prototype.sayName=function(){
    console.log(this.name);
}
var person1=new Person();
person1.sayName();
var person2=new Person();
person2.sayName();
console.log(person1.sayName==person2.sayName);```
- 组合使用构造函数模式和原型模式:构造函数定义实例属性,原型定义共享的属性和方法。

//组合使用构造函数和原型方式
//优点:结合了构造函数和原型情势的亮点,并解决了缺陷
//缺点:代码没有被很好地卷入起来
function Person(name,age,job){
this.name=name;
this.age=age;
this.job=student;
this.friends=[“num1″,”num2”];
}
Person.prototype={
constructor:Person,
sayName:function(){
console.log(this.name);
}
}
var person1=new Person(“masike”,19,”student”);
var person2=new Person(“withershins”,19,”worker”);
person1.friends.push(“vash”);
console.log(person1.friends);
console.log(person2.friends);
console.log(person1.friends===person2.friends);
console.log(person1.sayName===person2.sayName);“`

JavaScript 深切之创立对象的种种主意以及优缺点

2017/05/28 · JavaScript
· 对象

初稿出处: 冴羽   

var person1 = new Person();

深深连串

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
  14. JavaScript
    深远之创设对象的三种方式以及优缺点

    1 赞 3 收藏
    评论

图片 1

JavaScript继承情势总括

继续:超类构造函数中有总体性有办法,超类原型中有总体性有办法,子类想要继承超类的构造函数,超类原型中的部分属性和办法,于是便有了几次三番。

//原型链的继承
//缺点:对象实例共享所有的属性和方法,因此不适合单独使用。
function Parent(){
    this.name="mike";
}
function Child(){
    this.age=19;
}
Child.prototype=new Parent();//子类原型等于父类实例
var test =new Child();
console.log(test.age);
console.log(test.name);

function Brother(){
    this.weight=60;
}
Brother.prototype=new Child();
var brother=new Brother();
console.log(brother.name);
console.log(brother.age);```

- 借用构造函数模式

//借用构造函数/类式继承call()/apply()
//可以传递参数,不过方法无法共享
function Parent(age){
this.name=[‘mike’,’jack’,’smith’];
this.age=age;
}
function Child(age){
Parent.call(this,age);
}
var test=new Child(21);
console.log(test.age);//21
console.log(test.name);//mike,jack,smith
test.name.push(‘bill’);
console.log(test.name);//mike,jack,smith,bill

//call()和apply()用法分别
The difference is that apply lets you invoke the function with arguments
as an array;
call requires the parameters be listed explicitly.
A useful mnemonic is “A for array and C for comma(逗号).”“`

//组合式继承
//组合构造函数和原型链
//原型链继承原型属性和方法,构造函数实现实例属性的继承
function Parent(name){
    this.name=name;
    this.arr=['aaa','bbb','ccc'];
}

Parent.prototype.run=function(){
    return this.name;
};

function Child(name,age){
    Parent.call(this,age);//第二次调用
    this.age=age;
}

Child.prototype=new Parent();//第一次调用```

- 原型式继承:不必预先定义构造函数的情况下实现继承,本质是执行给定对象的浅复制,而复制的副本还可以得到进一步的改造。

//借助于原型并根据已部分对象成立新指标,同时还不用成立自定义类型
function obj(o){
function F(){}
F.prototype=o;
return new F();
}
var box={
name:”masike”,
arr:[‘baba’,’mama’,’didi’]
};
var b1=obj(box);
console.log(b1.name);//masike

b1.name=’mike’;
console.log(b1,name);//mike

console.log(b1,arr);//baba,mama,didi
b1.arr.push(“parents”);
console.log(b1.arr);//baba,mama,didi,parents

var b2=obj(box);
console.log(b2.name);//masike
console.log(b2.arr);//baba,mama.didi,parents

- 寄生式继承:基于某个对象后某些信息创建一个对象,然后增强对象,最后返回对象。

function create(o){
var f=obj(o);
f.run=function(){
return this.arr;
}
return f;
}“`

//寄生组合式类型
//解决了父类构造函数两次调用问题
function obj(o){  //(原型式)
    function F(){}
    F.prototype=o;
    return new F();
}
function create(parent,test){
    var f=obj(parent.prototype);//创建对象
    f.constructor=test;//增强对象
}
function Parent(name){
    this.name=name;
    this.arr=['brother','sister','parents'];
}

Parent.prototype.run=function(){
    return this.name;
}
function Child(name,age){
    Parent.call(this,name);
    this.age=age;
}
Child.prototype = obj(Parent.prototype);//实现继承

var test=new Child("masike",19);
test.arr.push("withershins");
console.log(test.arr);
console.log(test.run());//只共享了方法

var test2=new Child("jack",22);
console.log(test2.arr);//引用问题解决```

未完待续......
>继承最推荐的解决方案:

         if(!Object.create){//object.create()是ES5新增方法
                Object.create= (function(){
                    function F(){}   //创建中介函数(bridge)
                    return function(obj) {
                        if(arguments.length !== 1) {
                            throw new Error("仅支持一个参数");
                        }
                        F.prototype = obj;   //原形绑定
                        return new F();      //返回实例
                    }
                })()
        //最终返回的结果,既是F的实例属性,享有F构造函数中的所有属性和方法(因为F构造函数为空,所以完全不用担心会有多余不想要的属性方法存在),[[prototype]]又指向F.prototype,返回的结果是一个对象!!!
        }
        function Person(name, age) {
                this.name = name;
                this.age = age;
        }
        Person.prototype.walk = function() {//写到了prototype中,walk一定是想要共享的方法
                console.log("走路....");
        } 
        function Child(name, age, address) {
                Person.call(this, name, age);//这里继承了person构造函数中想要传递的一些属性
                this.address = address;
        }
        Child.prototype = Object.create(Person.prototype);//不要再使用new了!
        Child.prototype.talk = function() {
            console.log("说话ing.....")
        }
        //不用new的原因是因为你不想要Child继承Person构造函数中的所有属性和方法,而是想让他单独继承Person.prototype中共享的属性和方法。```

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

率先新建多少个对象

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

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

缺点:

方法都在构造函数中定义,每便创制实例都会创立三次方法。

JavaScript创建对象方法总括杰出博文
javascript继承讲解精粹博文
于江水
继承讲解

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

亮点:化解了每一种方法都要被重新成立的题材

症结:那叫什么封装……

var colors = new SpecialArray(‘red’, ‘blue’, ‘green’);

5. 寄生式继承

始建四个仅用于封装继承进度的函数,该函数在中间以某种方式来做增长对象,最终回到对象。

function createObj (o) { var clone = object.create(o); clone.sayName =
function () { console.log(‘hi’); } return clone; }

1
2
3
4
5
6
7
function createObj (o) {
    var clone = object.create(o);
    clone.sayName = function () {
        console.log(‘hi’);
    }
    return clone;
}

症结:跟借用构造函数形式一样,每一回创立对象都会成立二次方法。

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 操作符调用构造函数

稳当对象最符合在一部分安然无恙的环境中。

稳当构造函数情势也跟工厂情势一样,不只怕分辨对象所属类型。

person1.sayName(); // kevin

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)

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

结缘继承最大的老毛病是会调用四次父构造函数。

2次是安装子类型实例的原型的时候:

Child.prototype = new Parent();

1
Child.prototype = new Parent();

3回在成立子类型实例的时候:

var child1 = new Child(‘kevin’, ’18’);

1
var child1 = new Child(‘kevin’, ’18’);

回忆下 new 的模拟完结,其实在那句中,大家会实施:

Parent.call(this, name);

1
Parent.call(this, name);

在此间,我们又会调用了二次 Parent 构造函数。

于是,在那几个例子中,如若大家打字与印刷 child1 对象,大家会意识 Child.prototype
和 child1 都有1性情能为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);

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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深切系列推断写十五篇左右,意在帮大家捋顺JavaScript底层知识,重点讲解如原型、效率域、执行上下文、变量对象、this、闭包、按值传递、call、apply、bind、new、继承等难点概念。

设若有不当可能不如临深渊的地点,请务必给予指正,13分感激。假如喜欢也许具有启发,欢迎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 赞 收藏
    评论

图片 2

Person.prototype.getName = function () {

4.原型式继承

function createObj(o) { function F(){} F.prototype = o; return new F();
}

1
2
3
4
5
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”]

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

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

安妥构造函数模式也跟工厂形式一样,无法辨认对象所属类型。

写在前边

本文讲解JavaScript种种继承格局和优缺点。

但是注意:

那篇小说更像是笔记,哎,再让本人感慨一句:《JavaScript高级程序设计》写得真是太好了!

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

}

JavaScript 浓密之继续的二种格局和优缺点

2017/05/28 · JavaScript
· 继承

原稿出处: 冴羽   

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

缺陷:原型情势该有的弱项仍然有

};

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

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

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. 不能发轫化参数

    if (typeof this.getName != “function”) {

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

亮点:实例能够分辨为三个一定的品种

症结:每一回创建实例时,每一个方法都要被创设一回

            }

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

缺陷:对象不可能辨识,因为兼具的实例都针对三个原型

        }

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

优点:该共享的共享,该民用的个体,使用最广大的不二法门

缺陷:有的人正是期望一切都写在一块儿,即更好的封装性

    }

缺陷:原型格局该有的老毛病依旧有

缺陷:重写了原型,丢失了constructor属性

Person.prototype = {

所谓妥贴对象,指的是不曾集体性质,而且其格局也不引用 this 的对象。

而是值得说的是,上边例子中的循环:

}

}

5.1 寄生构造函数情势

    };

优点:实例能够识别为两个特定的花色

与寄生构造函数形式有两点分歧:

        console.log(this.name);

            console.log(this.name);

    }

    var o = new Object();

}

    console.log(this.name);

function getName() {

    }

}

console.log(person1 instanceof Person) // false

                console.log(this.name);

}

};

Person.prototype = {

var person1 = new Person(‘kevin’);

分解下怎么:

    o.getName = function () {

Person.prototype = {

var person1 = new Person(‘kevin’);

    var o = new Object();

var person2 = new Person(‘daisy’);

    getName: function () {

}

person2.getName();

var person1 = createPerson(‘kevin’);

    };

相关文章

发表评论

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

网站地图xml地图