国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

我來(lái)重新學(xué)習(xí) javascript 的面向?qū)ο螅╬art 2)

silvertheo / 642人閱讀

摘要:先來(lái)說其實(shí)構(gòu)造函數(shù)也有,原型對(duì)象有,實(shí)例有也有,或者更加籠統(tǒng)的說,所有對(duì)象都是有的。構(gòu)造函數(shù)的原型對(duì)象上的會(huì)指向構(gòu)造函數(shù)。由于屬性是可以變更的,所以未必真的指向?qū)ο蟮臉?gòu)造函數(shù),只是一個(gè)提示。

續(xù)上一集內(nèi)容,通過構(gòu)造函數(shù)的方式,成功地更新了生產(chǎn)技術(shù),老板笑呵呵,工人少奔波,只是問題總比辦法多,又遇到一個(gè)新問題,就是會(huì)造成一些資源的重復(fù)和浪費(fèi),那么經(jīng)過工程師們的智慧交流,他們產(chǎn)生了一個(gè)新技術(shù),原型模式。

一、使用原型模式
function Food() {}

Food.prototype.name = "蘋果";
Food.prototype.sayName = function() {
  console.log("我是" + this.name);
};

var food1 = new Food();
food1.sayName();

var food2 = new Food();
food2.sayName();
// 創(chuàng)建無(wú)限多的 food 。。。。。。

console.log(food1.sayName == food2.sayName); // 返回 true

將所有屬性和方法,包括sayName 方法都放到原型Food的原型上去

跟之前構(gòu)造函數(shù)創(chuàng)建新對(duì)象的方式一樣,使用new來(lái)創(chuàng)建

這樣就完成了原型模式的使用了,能夠?qū)⒑瘮?shù)進(jìn)行共享,不用每次都重復(fù)創(chuàng)建不同的函數(shù)實(shí)例了,而且所有的屬性共享,也能夠很方便節(jié)省代碼和簡(jiǎn)化結(jié)構(gòu),其他人也可以很方便地進(jìn)行使用。

但是比較懵逼,為什么這樣就可以了呢?原型是個(gè)什么東西?怎么起作用的呢?

1.1 理解什么是原型

在《javascript 高級(jí)程序設(shè)計(jì)》里面是這樣說的,我們創(chuàng)建的每個(gè)函數(shù)都有一個(gè) prototype,這個(gè)屬性是一個(gè)內(nèi)存指針,指向一個(gè)對(duì)象,而這個(gè)對(duì)象的用途是包含可以由特定類型的所有實(shí)例共享的屬性和方法。

換句大白話來(lái)說:

原型就是根,所有東西都有根,是來(lái)自于哪里,是被誰(shuí)創(chuàng)造出來(lái)的,并且能夠通過這個(gè)根去追溯父輩祖輩的信息。

全部東西都會(huì)由原型創(chuàng)造,所以都會(huì)帶有一個(gè)原型屬性,只是不同的原型創(chuàng)造出來(lái)的東西帶有不同的原型屬性。

例如圖1,可以粗獷地理解為蛋是雞生的,所以蛋的原型是雞。

圖片引用來(lái)自:https://hackernoon.com/unders...

或者用親屬關(guān)系來(lái)理解,原型就是你的父輩祖輩。

圖片引用自http://china.findlaw.cn/info/...

例如圖2,這是一個(gè)類樹狀結(jié)構(gòu)的組織:

圖片引用自:http://rohitnsit08.blogspot.c...

這里的global object 的意思在后面有解釋。

從這個(gè)圖可以看到,各種不同過的對(duì)象,都會(huì)有不同的原型,string 的原型就是 string.prototype,function 的原型就是 string.prototype 等等,而這些原型的原型就是Object.prototype了,所以就有那么一句話,在 javascript 里面,所有的東西都是對(duì)象

在 javascript 里面,global object 有4種:

在瀏覽器里面,windows 被稱作是 global object

在 nodejs 里面,nodejs 的運(yùn)行本身也是一個(gè) global objec

在 Worker 線程下, WorkerGlobalScope 也叫 global object

在一般 javascript 運(yùn)行過程中,在所有對(duì)象被創(chuàng)建之前,會(huì)預(yù)先創(chuàng)建一個(gè) global object,里面包含了所有這個(gè) javascript 引擎里面擁有的屬性和方法,這個(gè)也叫做 global object,并且 javascript 的對(duì)象系統(tǒng)都是基于這個(gè) global object 建立的。

1.2 理解什么是 constructor 和構(gòu)造函數(shù)的 prototype 和 [[prototype]]

其實(shí)原型是很好理解的東西,就是原來(lái)的形態(tài),例如string 的原型就是 string.prototype,字符串的原來(lái)的形態(tài)就是字符串原型,但是還有一些比較影響理解和學(xué)習(xí)的東西,例如constructor prototype [[prototype]] 這些。

① 先來(lái)說constructor

其實(shí)構(gòu)造函數(shù)也有constructor,原型對(duì)象有constructor,實(shí)例有constructor 也有,或者更加籠統(tǒng)的說,所有對(duì)象都是有constructor的。

// 構(gòu)造函數(shù)的constructor,默認(rèn)構(gòu)造函數(shù)的原型對(duì)象是Function對(duì)象
function Food() {}
console.log(Food.constructor); // 返回[Function: Function]

// 實(shí)例的constructor是Food
var food1 = new Food("蘋果");
console.log(food1.constructor); // 返回 [Function: Food]

// 構(gòu)造函數(shù)的原型對(duì)象Food.prototype 也有constructor,指向構(gòu)造函數(shù)
console.log(Food.prototype.constructor); // 返回 [Function: Food]

構(gòu)造函數(shù)也是函數(shù),他的 constructor默認(rèn)會(huì)指向[Function: Function],也就是函數(shù)原型對(duì)象是他的原型對(duì)象。

當(dāng)使用 new 來(lái)實(shí)例化對(duì)象的時(shí)候,實(shí)例的constructor會(huì)默認(rèn)指向構(gòu)造函數(shù),證明是哪一個(gè)來(lái)自于哪一個(gè)構(gòu)造函數(shù),但是僅此而已,只是一個(gè)標(biāo)識(shí),所以是 Food

構(gòu)造函數(shù) 的原型對(duì)象 Food Prototype上的constructor會(huì)指向構(gòu)造函數(shù) Food。

可以看出,通過 constructor 可以看到他們之間的關(guān)系,但是通過constructor連接的關(guān)系是很脆弱的(容易變化,不可靠),也因?yàn)?javascript 在設(shè)計(jì)當(dāng)初并沒有太多考慮這個(gè)情況,所以constructor比較雞肋。

另外雖然有這么多constructor,但是我們一般討論的比較多的是,原型對(duì)象的constructor,他會(huì)默認(rèn)指向構(gòu)造函數(shù)的 prototype 屬性,僅此而已,如果他沒有被改變的話,也可以充當(dāng)一種標(biāo)志,代表通過這個(gè)構(gòu)造函數(shù)生成的實(shí)例是來(lái)自哪個(gè)原型的,從而判斷對(duì)象的類型是哪一種(但不可靠)。

舉例說明:

function Food() {}
console.log(Food.constructor); // 返回[Function: Function]

// 當(dāng)重寫原型的時(shí)候,實(shí)例的constructor 就變成了[Function: Object]
Food.prototype = {
  name: "蘋果"
};
var food2 = new Food("蘋果");
console.log(food2.constructor); // 返回 [Function: Object]

這里實(shí)例的constructor就被改變了,所以一般我們可以看到重寫原型的時(shí)候(原型鏈被切斷,會(huì)默認(rèn)指向默認(rèn)的原型對(duì)象),會(huì)手動(dòng)加入一個(gè) constructor 屬性來(lái)指定它的值,以方便識(shí)別。

function Food() {}
console.log(Food.constructor); // 返回[Function: Function]
// 我們需要主動(dòng)標(biāo)記 constructor屬性
Food.prototype = {
  constructor: Food,
  name: "蘋果"
};
var food2 = new Food("蘋果");
console.log(food2.constructor); // 返回 [Function: Food]
constructor其實(shí)沒有什么用處,他是JavaScript語(yǔ)言設(shè)計(jì)的歷史遺留物。由于constructor屬性是可以變更的,所以未必真的指向?qū)ο蟮臉?gòu)造函數(shù),只是一個(gè)提示。不過,從編程習(xí)慣上,我們應(yīng)該盡量讓對(duì)象的constructor指向其構(gòu)造函數(shù),以維持這個(gè)慣例。--by 賀師俊

② 再來(lái)說prototype

在 javascript 里面,只要是函數(shù),都會(huì)有這樣一個(gè)屬性prototype,這個(gè)屬性指向函數(shù)的原型對(duì)象,在默認(rèn)情況下,所有原型對(duì)象都會(huì)自動(dòng)獲得一個(gè) constructor 屬性,指向prototype 所在的函數(shù)。

function Food() {}
console.log(Food.prototype) // 返回Food {}

var food1 = new Food("蘋果");

console.log(food1.prototype) // 返回 undefined

構(gòu)造函數(shù) Food 的prototype屬性是一個(gè)內(nèi)存指針,最終是指向 Food 的原型對(duì)象 Food Prototype 的,這里需要注意我的寫法,是 Food Prototype ,這里雖然很相似,但其實(shí)不是。

實(shí)例對(duì)象上的 prototype 屬性沒辦法直接查看,所以返回 undefined,需要用別的方法來(lái)查看。

③ 最后說說[[prototype]]__proto__

這是存在于實(shí)例身上的 prototype 屬性,但是沒辦法直接查看,只能通過某些方式來(lái)獲取和判斷。不同的瀏覽器有不同的叫法,的屬性名字也可能是[[prototype]] 或者_proto_。

// Object.getPrototypeOf會(huì)返回原型對(duì)象,但看起來(lái)跟普通構(gòu)造函數(shù)沒區(qū)別
console.log(Object.getPrototypeOf(food1)); // 返回 Food {}

// 所以一般會(huì)使用這個(gè)方式來(lái)判斷原型對(duì)象是否一致
console.log(Object.getPrototypeOf(food1) === Food.prototype); // 返回 true
// 或者這個(gè)方式,isPrototypeOf會(huì)直接判斷
console.log(Food.prototype.isPrototypeOf(food1)) // 返回 true
1.3 為什么能夠通過原型模式來(lái)解決問題呢?

原型的作用主流程:

在 javascript 里面,創(chuàng)建一個(gè)新函數(shù)(對(duì)象),都會(huì)在創(chuàng)建過程里面增加一個(gè)prototype屬性,也就是原型屬性,這個(gè)屬性指向構(gòu)造函數(shù)的原型對(duì)象,例如food1prototype屬性指向Food的原型對(duì)象Food prototype。

而這個(gè)被指向的原型對(duì)象里面也會(huì)自動(dòng)獲得一個(gè)constuctor構(gòu)造函數(shù)屬性,這個(gè)屬性里面包含了一個(gè)指向,指向之前被創(chuàng)建的對(duì)象的prototype屬性的所在位置,相當(dāng)于原型對(duì)象是母體,被創(chuàng)建的對(duì)象會(huì)關(guān)聯(lián)到母體身上,

javascript 解析器讀取到對(duì)象之后,會(huì)執(zhí)行一次搜索,如果在當(dāng)前對(duì)象上沒有搜索到目標(biāo)屬性的話,就會(huì)繼續(xù)搜索指針指向的原型對(duì)象,會(huì)不斷逐級(jí)查找(原型對(duì)象),直至找到為止。

參考前面所說的原型,constructor 和 prototype 的內(nèi)容來(lái)理解

在《javascript 高級(jí)程序設(shè)計(jì)》第三版里面的有一幅圖:

person1 和 person2 都是實(shí)例, Person 是構(gòu)造函數(shù),Person Prototype 是 Person 構(gòu)造函數(shù)的原型對(duì)象。

person1或者 person2 的[[Prototype]]都指向了Person Prototype

問什么這里會(huì)有一條線指向了構(gòu)造函數(shù)?

因?yàn)?b>Person 構(gòu)造函數(shù)的prototype 指向了Person Prototype,而Person Prototypeconstructor 也指向了Person 構(gòu)造函數(shù),他們之間通過這樣來(lái)互相確認(rèn)“關(guān)聯(lián)狀態(tài)”,但僅僅互相確認(rèn)關(guān)系而已(因?yàn)?constructor 容易被改變)。

類比到我們的 Food 例子里面去,food1和 FoodFood Prototype的關(guān)系就跟 person1和 person2和PersonPerson Prototype 的關(guān)系是一樣的。
二、 對(duì)于原型的一些使用技巧

① 如果需要查找這個(gè)實(shí)例對(duì)象的原型的話,可以使用Object.getPrototypeOf ,他會(huì)返回整個(gè)原型對(duì)象。

function Food() {}

Food.prototype.name = "蘋果";

Food.prototype.sayName = function() {
  console.log("我是" + this.name);
};

var food1 = new Food();
console.log(Object.getPrototypeOf(food1)) // 返回 Food { name: "蘋果", sayName: [Function] }

② 只能通過對(duì)象實(shí)例訪問保存在原型的值,不能通過對(duì)象實(shí)例來(lái)重寫原型中的值。
③ 對(duì)象實(shí)例可以重寫從原型對(duì)象中“繼承”過來(lái)的同名屬性,這時(shí)候會(huì)切斷對(duì)象實(shí)例和原型對(duì)象的某個(gè)同名屬性的聯(lián)系,如果想恢復(fù)聯(lián)系即恢復(fù)沒改過的同名屬性的話,可以使用delete刪除對(duì)象實(shí)例的某個(gè)屬性。
hasOwnProperty()方法可以檢測(cè)一個(gè)屬性是存在于實(shí)例中還是存在于原型中。

function Food() {}

Food.prototype.name = "蘋果";

Food.prototype.sayName = function() {
  console.log("我是" + this.name);
};

var food1 = new Food();

console.log(food1.hasOwnProperty("name")); // 返回 false
food1.name = "bilibili"; // 設(shè)置 food1的 name 屬性(也就是改寫從原型對(duì)象繼承過來(lái)的 name 屬性)
console.log(food1.hasOwnProperty("name")); // 返回 true
console.log(food1.name); // 返回 bilibili

⑤ 更簡(jiǎn)單的原型寫法

function Food() {}

Food.prototype = {
  constructor: Food, // 這里需要注意
  name: "蘋果",
};

如果不寫constructor的話,Food.prototype constructor就不再指向 Food ,這樣就沒辦法通過constructor來(lái)識(shí)別得到改對(duì)象實(shí)例是屬于哪個(gè)原型對(duì)象了。

以這種方式編寫原型的時(shí)候,如果主動(dòng)設(shè)置constructor,對(duì)象的[[Enumerable]] 可遍歷屬性就會(huì)被設(shè)置為 true,代表可以被遍歷。

⑥ 在原型對(duì)象上直接編輯修改,會(huì)即時(shí)反應(yīng)到實(shí)例對(duì)象上,所以可以隨時(shí)進(jìn)行修改,很方便。
⑦ 如果重寫原型對(duì)象,要注意原型對(duì)象的指向問題:

// 原型鏈會(huì)被切斷
function Food() {
}
var food1 = new Food("蘋果"); // 繼續(xù)指向原來(lái)的 Food.prototype(最初的那個(gè)原型對(duì)象)
// 重寫Food.prototype
Food.prototype = {
  constructor: Food,
  name: "蘋果",
};
console.log(food1.name); // 返回 undefined
// 原型鏈不會(huì)被切斷
function Food() {
}
// 先重寫Food.prototype
Food.prototype = {
  constructor: Food,
  name: "蘋果",
};
// 再實(shí)例化對(duì)象
var food1 = new Food("蘋果"); // 指向新的被重寫后的Food.prototype
console.log(food1.name); // 返回 蘋果

在 new 創(chuàng)建完實(shí)例之后,實(shí)例的原型對(duì)象是構(gòu)造函數(shù)的原型對(duì)象,如果在這時(shí)候重寫了構(gòu)造函數(shù)的原型對(duì)象的話,那么原來(lái)實(shí)例跟原來(lái)構(gòu)造函數(shù)的原型對(duì)象的鏈接就會(huì)被切斷,就無(wú)法使用原型對(duì)象上的數(shù)據(jù)了。

三、文末我們又遇到了新問題了

用了原型模式之后,雖然解決了遇到的一系列問題,但也帶來(lái)了一些新的副作用(怎么副作用那么多。。。。。),原型模式的共享特性帶來(lái)了方便之余,也造成了一些困擾,如果我們需要一些不想共享的信息,例如 food1 的原產(chǎn)地是巴西,印度,非洲,food2的原產(chǎn)地是巴西,印度,俄羅斯,他們之間有一些區(qū)別,不能完全共享,那么怎么辦呢?

會(huì)通過組合使用構(gòu)造函數(shù)模式和原型模式或者動(dòng)態(tài)原型模式來(lái)解決,下回分解。

參考內(nèi)容

紅寶書,《javascript 高級(jí)程序設(shè)計(jì)第三版》

版權(quán)信息
作者: 慫如鼠
網(wǎng)站: https://www.whynotbetter.com
本作品著作權(quán)歸作者所有,商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請(qǐng)注明出處。

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/108483.html

相關(guān)文章

  • 我來(lái)重新學(xué)習(xí) javascript 面向對(duì)象part 1)

    摘要:其實(shí)在之前的工廠模式里面,也存在這個(gè)問題,不過工廠模式更徹底,直接完全創(chuàng)建一個(gè)新對(duì)象,而構(gòu)造函數(shù)模式的話只是方法會(huì)被重新創(chuàng)建。 我來(lái)重新學(xué)習(xí) javascript 的面向?qū)ο螅╬art 1) 很多job 的描述都說要求精通 javascript 面向?qū)ο缶幊蹋歉鶕?jù)一般的套路,寫精通其實(shí)就是熟練,寫熟練其實(shí)就是一般,寫一般其實(shí)就是懵逼! showImg(https://segment...

    myshell 評(píng)論0 收藏0
  • 我來(lái)重新學(xué)習(xí) javascript 面向對(duì)象part 3)

    摘要:二動(dòng)態(tài)原型模式動(dòng)態(tài)原型模式的特點(diǎn)是,在構(gòu)造函數(shù)里面增加判斷處理是否添加原型對(duì)象屬性。他依然有一個(gè)嚴(yán)重的問題,就是原型對(duì)象和實(shí)例和構(gòu)造函數(shù)之間沒辦法關(guān)聯(lián),這樣不適合在有一定規(guī)模復(fù)雜度的程序開發(fā)中使用。 續(xù)上一集內(nèi)容,有一些數(shù)據(jù)不需要共享的時(shí)候,但是又想實(shí)現(xiàn)共享數(shù)據(jù)處理,魚與熊掌,都要兼得(老板就是這么霸氣),那么經(jīng)過工程師們的智慧交流,他們發(fā)現(xiàn)現(xiàn)實(shí)并非那么殘酷,還有一些辦法可取的,也就是...

    Elle 評(píng)論0 收藏0
  • 我來(lái)重新學(xué)習(xí)js面向對(duì)象part 4)

    摘要:我是的可以改變函數(shù)的對(duì)象的指向拋出異常,沒有這個(gè)因?yàn)樽宇惡统惗际菢?gòu)造函數(shù),那么就會(huì)有之前說的,構(gòu)造函數(shù)在的時(shí)候,里面的方法函數(shù)會(huì)重復(fù)創(chuàng)建實(shí)例,導(dǎo)致資源浪費(fèi)。 我來(lái)重新學(xué)習(xí)js 的面向?qū)ο螅╬art 4) 續(xù)上一篇,隨著業(yè)務(wù)越來(lái)越大,要考慮一些繼承的玩意了,大千世界,各種東西我們要認(rèn)識(shí)和甄別是需要靠大智慧去分門別類,生物學(xué)中把動(dòng)植物按界、門、綱、目、科、屬、種進(jìn)行分類的方法可能是最有代...

    MAX_zuo 評(píng)論0 收藏0
  • 我來(lái)重新學(xué)習(xí)js 面向對(duì)象part 5)

    摘要:無(wú)限增殖返回蘋果返回香蕉返回返回使用的新語(yǔ)法方法會(huì)創(chuàng)建一個(gè)新對(duì)象,使用現(xiàn)有的對(duì)象來(lái)提供新創(chuàng)建的對(duì)象的。是新增的,用來(lái)規(guī)范原型式繼承。這里將返回的新對(duì)象放到子類的原型對(duì)象里面,這樣子類就擁有了父類的原型對(duì)象,也就實(shí)現(xiàn)了方法的繼承。 這是最后的最后了,我會(huì)順便總結(jié)一下各種繼承方式的學(xué)習(xí)和理解。(老板要求什么的,管他呢) 一、繼承-組合繼承、偽經(jīng)典繼承 showImg(https://seg...

    BicycleWarrior 評(píng)論0 收藏0
  • 2017年 最好javascript 書籍

    摘要:請(qǐng)記住,這些書中的一些可能不是最新的,但概念和基礎(chǔ)仍應(yīng)適用。是最好的老師之一。的秘密由部分組成。在你完成這些書后,查看書籍和最好的本土?xí)? 我看過三本,第1本,第二本,第四本。第一本買的的實(shí)體書,其他兩本看的是電子書。第一本是大名鼎鼎老道寫的,書很薄,但是非常經(jīng)典。javascirpt忍者秘籍是jquery的作者寫的,也是非常經(jīng)典。you dont kown js系列也是非常好??戳?..

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

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

0條評(píng)論

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