成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

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

curlyCheng / 3343人閱讀

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

從對(duì)象聲明開(kāi)始一步步介紹

1.普通對(duì)象聲明

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

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

this的含義:

this表示當(dāng)前作用域下的對(duì)象;

this表示new Object()實(shí)例化出來(lái)的那個(gè)對(duì)象;

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

缺點(diǎn):要?jiǎng)?chuàng)建一個(gè)類似的對(duì)象會(huì)產(chǎn)生大量的代碼。

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

2.工廠模式

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

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

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

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

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

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

構(gòu)造函數(shù)可用來(lái)創(chuàng)建特定類型的對(duì)象,類似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,因?yàn)檫@里person1是從屬于Person

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

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

不用創(chuàng)建臨時(shí)對(duì)象,因?yàn)?new 會(huì)幫你做(你使用「this」就可以訪問(wèn)到臨時(shí)對(duì)象);

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

不用 return 臨時(shí)對(duì)象,因?yàn)?new 會(huì)幫你做;

不要給原型想名字了,因?yàn)?new 指定名字為 prototype。

persen1 和 person2 的 constructor 屬性都指向 Person

缺點(diǎn):每次實(shí)例化 Person,共有屬性 sayName 都會(huì)重復(fù)創(chuàng)建,和工廠模式問(wèn)題一樣。

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

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

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

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

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

缺點(diǎn):

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

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

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

4.原型模式

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

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

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

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

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

缺點(diǎn):重復(fù)敲Person.prototype,造成大量的重復(fù)輸入。

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

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

var person = new Person();

注意:

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

不能重寫(xiě)原型中的屬性,如 person.name = "Lisi",它會(huì)變成 person 的實(shí)例屬性。

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

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

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

function Person(name,age,job){        //保持獨(dú)立的使用構(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",引用類型沒(méi)有使用原型,所以沒(méi)有共享
alert(person1.friends == person2.friends);    //false
alert(person1.sayName == person2.sayName);    //true

注意:實(shí)例化的私有屬性是自有的

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

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

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

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

proto 和 prototype

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

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

之前寫(xiě)過(guò)一篇文章闡述它們之間的不同:前端學(xué)習(xí)筆記之原型——一張圖說(shuō)明prototype__proto__的區(qū)別

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/94546.html

相關(guān)文章

  • 當(dāng)我們?cè)贘avaScript中new一個(gè)對(duì)象的時(shí)候,我們到底在做什么

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

    woshicixide 評(píng)論0 收藏0
  • 繼承與原型

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

    My_Oh_My 評(píng)論0 收藏0
  • 自己實(shí)現(xiàn)一個(gè)簡(jiǎn)單的虛擬 DOM

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

    luffyZh 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<