JavaScript深刻之成立对象的有余格局以及优缺点,深刻之创设对象的种种方法以及优缺点

JavaScript 深远之创立对象的三种艺术以及优缺点

2017/05/28 · JavaScript
· 对象

初稿出处: 冴羽   

出自《JavaScript高端程序设计》

JavaScript 长远之继续的有余艺术和优缺点

2017/05/28 · JavaScript
· 继承

原稿出处: 冴羽   

JavaScript创建对象方法计算精粹博文
javascript承继疏解精粹博文
于江水
承接批注

写在前面

那篇文章讲授创制对象的各个艺术,以及优缺点。

然则注意:

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

  1. 工厂情势

写在前方

正文讲明JavaScript各类承袭情势和优缺点。

不过注意:

JavaScript深刻之成立对象的有余格局以及优缺点,深刻之创设对象的种种方法以及优缺点。那篇文章更像是笔记,哎,再让自身感慨一句:《JavaScript高档程序设计》写得真是太好了!

JavaScript成立对象格局总括

  • object构造函数、对象字面量

//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”);“`

  • 原型情势:使用prototype属性共享属性和章程。

//原型模式
//优点:公用原型减少了赘余
//缺点:在原型的改变会影响到所有的实例,于是实例没有了独立性
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);“`

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

症结:对象无法识别,因为具备的实例都针对1个原型

function createPerson(name) {

一.原型链承接

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

问题:

一.引用类型的特性被有着实例共享,举个例子:

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

贰.在创造 Child 的实例时,无法向Parent传参

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’];
JavaScript深刻之成立对象的有余格局以及优缺点,深刻之创设对象的种种方法以及优缺点。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中共享的属性和方法。```

二. 构造函数格局

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

二.借出构造函数(杰出几次三番)

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

优点:

一.防止了引用类型的品质被抱有实例共享

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

缺点:

主意都在构造函数中定义,每一回创立实例都会创设一遍方法。

二.一 构造函数方式优化

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;

三.整合承袭

原型链承接和经文再而三双剑合璧。

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 中最常用的继续情势。

三. 原型形式

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

优点:方法不会再也创造

缺点:壹. 具有的品质和办法都共享 二. 无法初阶化参数

    o.getName = function () {

四.原型式承袭

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 值。

3.一 原型方式优化

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

伍. 寄生式承继

创办二个仅用于封装承继进度的函数,该函数在里边以某种形式来做拉长对象,最终回来对象。

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

症结:跟借用构造函数形式同样,每一趟创设对象都会创制1回方法。

三.二 原型格局优化

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

缺陷:原型格局该有的弱项如故有

    };

陆. 寄生组合式承袭

为了便利大家阅读,在此间再一次一下重组承继的代码:

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)

组合继承最大的瑕疵是会调用五遍父构造函数。

1回是安装子类型实例的原型的时候:

Child.prototype = new Parent();

1
Child.prototype = new Parent();

二次在创造子类型实例的时候:

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

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

记念下 new 的一成不改变完毕,其实在那句中,大家会举办:

Parent.call(this, name);

1
Parent.call(this, name);

在此间,大家又会调用了三次 Parent 构造函数。

于是,在那几个事例中,假若我们打字与印刷 child一 指标,大家会发觉 Child.prototype
和 child1 都有三个性质为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 child一 =
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高端程序设计》中对寄生组合式承袭的夸赞正是:

那种办法的高功效彰显它只调用了1回 Parent 构造函数,并且为此制止了在
Parent.prototype
上边创造不供给的、多余的属性。与此同时,原型链仍是能够保险不改变;由此,还能健康使用
instanceof 和
isPrototypeOf。开拓人士普及感到寄生组合式承继是引用类型最奇妙的持续范式。

四. 组合方式

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

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;

深切体系

JavaScript深远种类目录地址:。

JavaScript浓密连串估计写十5篇左右,意在帮大家捋顺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

四.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 person一 = new
Person(‘kevin’); var person二 = new Person(‘daisy’); // 报错 并从未该方法
person一.getName(); // 注释掉下边包车型大巴代码,那句是足以实施的。
person贰.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

寄生构造函数格局,作者个人感到应当这么读:

寄生-构造函数-格局,也便是说寄生在构造函数的1种格局。

也便是说打着构造函数的品牌挂羊头卖狗肉,你看创造的实例使用 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,实际上两者的结果是1律的。

只是笔者恐怕是希望能像使用普通 Array 同样使用 SpecialArray,尽管把
特略Array 当成函数也一致能用,可是那并不是小编的原意,也变得不优雅。

在能够选取任何方式的情形下,不要使用这种模式。

但是值得一提的是,上边例子中的循环:

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

伍.二 得当构造函数形式

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深刻连串测度写10伍篇左右,目的在于帮大家捋顺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

  1. 构造函数格局

function Person(name) {

    this.name = name;

    this.getName = function () {

        console.log(this.name);

    };

}

var person1 = new Person(‘kevin’);

可取:实例能够识别为二个特定的档次

缺陷:每一次创建实例时,每种方法都要被创立一回

2.一 构造函数形式优化

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. 装有的品质和章程都共享 贰. 不能够初叶化参数

三.壹 原型形式优化

function Person(name) {

}

Person.prototype = {

    name: ‘kevin’,

    getName: function () {

        console.log(this.name);

    }

};

var person1 = new Person();

var person1 = new Person();

优点:封装性好了一点

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

三.贰 原型格局优化

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

可取:该共享的共享,该民用的个体,使用最广泛的方法

症结:有的人正是愿意一切都写在联合签字,即更加好的封装性

四.壹 动态原型情势

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 person一 = new Person(‘kevin’)。

万一对 new 和 apply
的底层试行进度不是很熟稔,能够翻阅尾部相关链接中的作品。

咱俩记念下 new 的完毕步骤:

先是新建一个指标

下一场将对象的原型指向 Person.prototype

然后 Person.apply(obj)

归来这一个目标

在意那个时候,回看下 apply 的落到实处步骤,会进行 obj.Person
方法,那年就会执行 if 语句里的始末,注意构造函数的 prototype
属性指向了实例的原型,使用字面量格局平素覆盖
Person.prototype,并不会转移实例的原型的值,person一依然是指向了原先的原型,而不是 Person.prototype。而此前的原型是不曾
getName 方法的,所以就报错了!

1经你尽管想用字面量格局写代码,能够品味下那种:

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

⑤.壹 寄生构造函数方式

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,就算把
特略Array 当成函数也同等能用,不过那并不是小编的本心,也变得不优雅。

在能够选拔任何格局的景况下,不要采纳这种格局。

可是值得一提的是,上边例子中的循环:

for (var i = 0, len = arguments.length; i < len; i++) {

    values.push(arguments[i]);

}

能够替换来:

values.push.apply(values, arguments);

五.贰 妥善构造函数形式

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

妥贴对象最符合在局地安然无恙的环境中。

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

Leave a Comment.