成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

使用 new 操作符內(nèi)部到底在做什么

curlyCheng / 3389人閱讀

摘要:把方法移動到構(gòu)造函數(shù)外部把方法移至外面,這樣每次實例化內(nèi)部的只是全局的引用,這樣避免了重復。構(gòu)造函數(shù)什么體內(nèi)什么都沒有,如果有叫做實例方法,實力屬性缺點重復敲,造成大量的重復輸入。

從對象聲明開始一步步介紹

1.普通對象聲明

首先創(chuàng)建自定義對象的最簡單方式就是創(chuàng)建一個Object的實例,然后在為他們添加屬性和方法,如下所示:

var person = new Object();        //創(chuàng)建對象
person.name = "Nicholas";        //添加屬性
person.age = 29;
person.job = "teacher";
person.sayName = function(){    //添加方法
    return this.name
};

this的含義:

this表示當前作用域下的對象;

this表示new Object()實例化出來的那個對象;

this要放在一個作用域下,比如person.sayName()person下的方法,可用this表示方法本身。

缺點:要創(chuàng)建一個類似的對象會產(chǎn)生大量的代碼。

為了解決多個類似聲明的問題,用一種工廠模式,這種方法是為了解決實例化對象產(chǎn)生大量重復的代碼。

2.工廠模式

用函數(shù)來封裝以特定接口創(chuàng)建對象的細節(jié)。

function createPerson(name,age,job){    //創(chuàng)建對象
    var obj = new Object();                //添加屬性
    obj.name = name;
    obj.age = age;
    obj.job = job;
    obj.sayName = function(){            //添加方法
        return this.name
    };
    return obj;                            //返回對象引用
}

var person1 = createPerson("Zhangsan",29,"Teacher");    //實例化第一個對象
var person2 = createPerson("Lisi",34,"Doctor");        //實例化第二個對象
console.log(person2 instanceof Object)        //true

this的含義:
1.thisnew Object(),實例化出來的那個對象;
2.this要放在一個作用域下,比如obj.sayName(){},這是obj作用域下的的方法,可以用this來表示obj本身。

缺點:集中實例化函數(shù),解決了大量重復的代碼;從上面例子我們可以看出sayName是共有屬性,而我們每實例化一個函數(shù)都會創(chuàng)建sayName,這也造成了重復。

3.構(gòu)造函數(shù)模式

構(gòu)造函數(shù)可用來創(chuàng)建特定類型的對象,類似Object類型。

function Person(name,age,job){
    this.name = name;
    this.age = age;
    this.job = job;
    this.sayName = function(){
        return this.name
    };
}

function Person2(name,age,job){
    this.name = name;
    this.age = age;
    this.job = job;
    this.sayName = function(){
        return this.name
    };
}

var person1 = new Person("Zhangsan",29,"Teacher");
var person2 = new Person("Lisi",34,"Doctor");    
var person3 = new Person2("Wangwu",34,"Police");

alert(person1 instanceof Person);        //true,person1從屬于Person
alert(person2 instanceof Person);        //true,person2從屬于Person
alert(person3 instanceof Person2);        //true,person3從屬于Person2
alert(person1 instanceof Person2);        //false,因為這里person1是從屬于Person

alert(person1.sayName() == person2.sayName());    //true,構(gòu)造函數(shù)的方法的值是想等的
alert(person1.sayName == person2.sayName);    //false,比較的是引用地址

我們使用new操作符,到底是在做什么

不用創(chuàng)建臨時對象,因為 new 會幫你做(你使用「this」就可以訪問到臨時對象);

不用綁定原型,因為 new 會幫你做(new為了知道原型在哪,所以指定原型的名字為 prototype);

不用 return 臨時對象,因為 new 會幫你做;

不要給原型想名字了,因為 new 指定名字為 prototype。

persen1 和 person2 的 constructor 屬性都指向 Person

缺點:每次實例化 Person,共有屬性 sayName 都會重復創(chuàng)建,和工廠模式問題一樣。

3.1把方法移動到構(gòu)造函數(shù)外部

把 sayName 方法移至 Person 外面,這樣每次實例化 Person 內(nèi)部的 sayName 只是全局 sayName 的引用,這樣避免了重復。

function Person(name,age,job){
    this.name = name;
    this.age = age;
    this.job = job;
    this.sayName = sayName;
}

function sayName(){            //把構(gòu)造函數(shù)內(nèi)部的方法通過全局來實現(xiàn),引用地址一致
    return this.name
}

var person1 = new Person("Zhangsan",29,"Teacher");
var person2 = new Person("Lisi",34,"Doctor");    

缺點:

全局 sayName 函數(shù)和 Person 之間聯(lián)系不緊密,如果它們中間有很多代碼,sayName 就不知道是干嘛用的了;

如果方法很多,每個都是全局函數(shù),就沒封裝可言了;

用全局函數(shù)很容易覆蓋全局變量。

4.原型模式

使用原型對象的好處是可以讓所有對象實例共享它所包含的屬性和方法。

如果是實例方法,不同的實例化,它們的方法和地址是不一樣的,是唯一的;

如果是原型方法,那它們的地址是共享的,大家都一樣。

function Person(){}        //構(gòu)造函數(shù)什么體內(nèi)什么都沒有,如果有叫做實例方法,實力屬性

Person.prototype.name = "Zhangsan";
Person.prototype.age = 29;
Person.prototype.job = "Teacher";
Person.prototype.sayName = function(){
    return this.name
};

var person1 = new Person();
person.sayName()     //Zhangsan

var person2 = new Person();
person.sayName()     //Zhangsan

alert(person1.sayName === person2.sayName);    //true

缺點:重復敲Person.prototype,造成大量的重復輸入。

4.1字面量方式創(chuàng)建原型
function Person(){}//使用字面量的方式創(chuàng)建原型對象,這里的`{}`就是對象,是`Object`,`new Object`相當于`{}`

Person.prototype = {
    constructor:Person,    //強行指向?qū)嵗?    name: "Zhangsan",
    age: 29,
    job: "Teacher",
    sayName: function(){
        return this.name
    }
};

var person = new Person();

注意:

實例化后重寫原型對象,會切斷現(xiàn)有實例和新原型之間的聯(lián)系

不能重寫原型中的屬性,如 person.name = "Lisi",它會變成 person 的實例屬性。

缺點:constructor不在指向?qū)嵗?,而會指?b>Object。新對象的constructor重寫Person原來的constructor,因此會指向新對象。
解決方法:在原型內(nèi)部,可以設(shè)置constructor強行執(zhí)行實例。

4.2組合構(gòu)造函數(shù)模式和原型模式

構(gòu)造函數(shù)模式用于定義實力屬性,原型模式用于定義方法和共享屬性

function Person(name,age,job){        //保持獨立的使用構(gòu)造函數(shù)
    this.name = name;
    this.age = age;
    this.job = job;
    this.friends = ["Xiaoming","Fangfang"];
}

Person.prototype = {        //保存共享的使用原型
    constructor: Person,
    sayName: function(){
        return this.name
    }
}

var person1 = new Person("Zhangsan",29,"Teacher");
var person2 = new Person("Wangwu",34,"Doctor");

person1.friends.push("Xiaohong");
alert(person1.friends);    //"Xiaoming,Fangfang,Xiaohong"
alert(person2.friends);    //"Xiaoming,Fangfang",引用類型沒有使用原型,所以沒有共享
alert(person1.friends == person2.friends);    //false
alert(person1.sayName == person2.sayName);    //true

注意:實例化的私有屬性是自有的

5.動態(tài)原型模式

動態(tài)原型模式,把所有信息都封裝在了構(gòu)造函數(shù)中。

function Person(name,age,job){        //保持獨立的使用構(gòu)造函數(shù)
    this.name = name;
    this.age = age;
    this.job = job;
    this.friends = ["Xiaoming","Fangfang"];
    
    if(typeof this.sayName != "function"){    //僅在第一次時初始化
        Person.prototype.sayName = function(){
            console.log(this.name);
        };
    }
}

原型的初始化,只要第1次初始化,就可以了,沒必要每次構(gòu)造函數(shù)實例化的時候都初始化,可以將原型封裝在函數(shù)里。
注意:使用動態(tài)原型模式時,不能使用對象字面量重寫原型。如果在已經(jīng)創(chuàng)建了實例的情況下重寫原型,那么就會切斷現(xiàn)有實例與新原型之間的聯(lián)系。

proto 和 prototype

__proto__:是實例化后的原型屬性
prototype:是 JS 內(nèi)部提供的原型屬性

上面例子中
person1.__proto__ === Person.prototype
person1.__proto__.__proto__ === Object.prototype

之前寫過一篇文章闡述它們之間的不同:前端學習筆記之原型——一張圖說明prototype__proto__的區(qū)別

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/94546.html

相關(guān)文章

  • 當我們在JavaScript中new一個對象的時候,我們到底在做什么

    摘要:當構(gòu)造函數(shù)沒有顯式地返回一個值的時候,對其執(zhí)行操作之后,會返回這個構(gòu)造函數(shù)實例化之后的對象。 JavaScript里實例化一個對象的時候,我們常用的方法就是使用new操作符。 var Foo = function(x, y) { this.x = x this.y = y } var foo = new Foo(1, 2) // Foo?{x: 1, y: 2} 那么...

    woshicixide 評論0 收藏0
  • 繼承與原型

    摘要:既然構(gòu)造函數(shù)有屬于自己的原型對象,那么我們應(yīng)該能讓另一個構(gòu)造函數(shù)來繼承他的原型對象咯我們在構(gòu)造函數(shù)內(nèi)部執(zhí)行了函數(shù)并改變了函數(shù)內(nèi)部的指向其實這個指向的是實例化之后的對象。 我們在討(mian)論(shi)JavaScript這門語言時,總是繞不過的一個話題就是繼承與原型鏈。那么繼承與原型鏈到底是什么呢? 我很喜歡的一個聊天模式是:我不能說XX是什么,我只能說XX像什么。也就是說我不直接跟...

    My_Oh_My 評論0 收藏0
  • 自己實現(xiàn)一個簡單的虛擬 DOM

    摘要:直到內(nèi)部的全部循環(huán)結(jié)束為止,才進入下一個元素,當循環(huán)結(jié)束時,內(nèi)部的節(jié)點都已經(jīng)生成好了。 自己實現(xiàn)虛擬 DOM 從 HTML 中提煉數(shù)據(jù)結(jié)構(gòu) 先來看下我們的 HTML 傅雷家書 讀家書,想付雷 從 HTML 中我們可以抽離出它的數(shù)據(jù)結(jié)構(gòu): 首先頁面中只需要一個根節(jié)點root,定義為:nodesDate數(shù)組 root內(nèi)有兩個子元素h1和span,數(shù)組有兩項,每項為內(nèi)...

    luffyZh 評論0 收藏0

發(fā)表評論

0條評論

閱讀需要支付1元查看
<