摘要:前言我們在深入淺出面向?qū)ο蠛驮透拍钇谶@篇文章中了解到了如何使用解決重復(fù)創(chuàng)建浪費內(nèi)存的問題,其中的關(guān)鍵就是,那么這篇文章讓我們來重新了解的前世今生一個苦逼年級主任的故事開學(xué)啦高一年級主任龔主任需要為全年級每一位理科班新生錄入學(xué)號并為每一位
前言
我們在深入淺出面向?qū)ο蠛驮汀靖拍钇?】在這篇文章中了解到了如何使用new Function解決重復(fù)創(chuàng)建浪費內(nèi)存的問題,其中的關(guān)鍵就是new,那么這篇文章讓我們來重新了解new的前世今生
一個苦逼年級主任的故事
開學(xué)啦~~~高一年級主任龔主任需要為全年級每一位理科班新生錄入學(xué)號并為每一位學(xué)生生成相關(guān)檔案
不僅要自己留一份而且要把每一個檔案都上傳到學(xué)校資料庫
哇,全年級一千個學(xué)生,一個個輸入,不要命啦?
還好龔主任學(xué)過編程
// 先造一個對象,把相關(guān)數(shù)據(jù)都先寫進去,看看是啥樣的 var 學(xué)生 = { 學(xué)號: 1, 年級: "高一", 所選方向: "理科班", 上傳資料: function () {/*上傳資料的代碼*/ } } // 不錯,檔案大致就是如此 // 再來個數(shù)組自己留著作為備份 // 那么循環(huán)一千次吧 var 全年級學(xué)生 = [] for (var i = 0; i < 1000; i++) { var 學(xué)生 = { 學(xué)號: i, 年級: "高一", 所選方向: "理科班", 上傳資料: function () {/*上傳資料的代碼*/} } 全年級學(xué)生.push(學(xué)生) }
龔主任突然想到,他昨天晚上在才在segmentfault上看到有關(guān)于內(nèi)存浪費的文章——深入淺出面向?qū)ο蠛驮汀靖拍钇?】
那么他寫的這個代碼就是典型的內(nèi)存浪費啊
每個學(xué)生除了學(xué)號不同,其它都相同,咋辦呢?
哎對了,那篇文章說可以通過原型和原型鏈解決這個問題
那么試試吧
// 先創(chuàng)建一個學(xué)生原型,然后把相同的代碼都放在這里 var 學(xué)生原型 = { 年級: "高一", 所選方向: "理科班", 上傳資料: function () {/*上傳資料的代碼*/} } // 重新寫循環(huán)代碼 var 全年級學(xué)生 = [] for (var i = 0; i < 1000; i++) { var 學(xué)生 = { 學(xué)號: i } // 還記得嗎,每個對象自動帶有__proto__屬性 // 不過在這里__proto__屬性的指向需要我們自己去設(shè)定 學(xué)生.__proto__ = 學(xué)生原型 全年級學(xué)生.push(學(xué)生) }
好了,大功告成,這下內(nèi)存不浪費了
但是,龔主任聽說程序猿寫代碼都追求可讀性強,他這寫的太不優(yōu)雅了
再改改吧
// 優(yōu)雅的代碼離不開封裝,現(xiàn)在讓我們來封裝封裝吧 function 學(xué)生(學(xué)號) { // 我們先建立一個臨時對象,把例如學(xué)號之類需要改變的屬性放進去 var 臨時對象 = {} 臨時對象.學(xué)號 = 學(xué)號 // 再把臨時對象的__proto__手工綁定到學(xué)生.原型 臨時對象.__proto__ = 學(xué)生.原型 return 臨時對象 } 學(xué)生.原型 = { 年級: "高一", 所選方向: "理科班", 上傳資料: function () {/*上傳資料的代碼*/ } } // 好了,開始循環(huán)吧 var 學(xué)生們 = [] for (var i = 0; i < 1000; i++) { 學(xué)生們.push(學(xué)生(i)) }
好了,讓我們先遠離一下龔先生和他的代碼,來看看到底什么是new
function 學(xué)生(學(xué)號) { // 我們先建立一個臨時對象,把例如學(xué)號之類需要改變的屬性放進去 // 【new做的第一件事:幫你創(chuàng)立一個臨時對象,臨時對象通過this訪問】 var 臨時對象 = {} 臨時對象.學(xué)號 = 學(xué)號 // 再把臨時對象的__proto__手工綁定到學(xué)生原型 // 【new做的第二件事:幫你自動把__proto__綁定到學(xué)生.原型】 臨時對象.__proto__ = 學(xué)生.原型 // 【new做的第三件事:幫你return臨時對象】 return 臨時對象 } // 【但new只有一個要求:把學(xué)生原型改名為 學(xué)生.prototype】 學(xué)生.原型 = { 年級: "高一", 所選方向: "理科班", 上傳資料: function () {/*上傳資料的代碼*/} }
那么,我們用new該怎么寫?so easy。new幫你做的事,你還自己做它干嘛呢?
function 學(xué)生(學(xué)號) { // 【new做的第一件事:幫你創(chuàng)立一個臨時對象,臨時對象通過this訪問】 // 所以我們不用創(chuàng)建臨時對象了,把下面那行代碼注釋掉 // var 臨時對象 = {} // 把臨時對象都改為this就好 this.學(xué)號 = 學(xué)號 // 再把臨時對象的__proto__手工綁定到學(xué)生原型 // 【new做的第二件事:幫你自動把__proto__綁定到學(xué)生原型】 // 我們不用手動綁定了,注釋掉 // 臨時對象.__proto__ = 學(xué)生原型 // 【new做的第三件事:幫你return臨時對象】 // 我們不用手動return了,注釋掉 // return 臨時對象 } // 【但new只有一個要求:把學(xué)生原型改名為 學(xué)生.prototype】 // new 幫了我們這么多忙,按照他的意思來唄,改了! 學(xué)生.prototype = { 年級: "高一", 所選方向: "理科班", 上傳資料: function () {/*上傳資料的代碼*/} } var 學(xué)生們 = [] for (var i = 0; i < 1000; i++) { 學(xué)生們.push(new 學(xué)生(i))
我的天哪,我們的代碼竟然通過new減少了這么多!!constructor屬性
function test(id) { this.id = id } new test(1) console.log(test.prototype) // {constructor: ?}
使用new操作符的時候,為了記錄臨時對象是由哪個函數(shù)創(chuàng)建的,會在prototype里添加一個constructor屬性,指向創(chuàng)建臨時對象的函數(shù)
注意:如果直接給prototype賦值,則constructor屬性會消失
function 學(xué)生(學(xué)號) { this.學(xué)號 = 學(xué)號 } 學(xué)生.prototype = { 年級: "高一", 所選方向: "理科班", 上傳資料: function () {/*上傳資料的代碼*/} } var 學(xué)生們 = [] for (var i = 0; i < 1000; i++) { 學(xué)生們.push(new 學(xué)生(i)) } // 沒有出現(xiàn)constructor屬性 console.log(學(xué)生.prototype) // {年級: "高一", 所選方向: "理科班", 上傳資料: ?}
可以采用另一種賦值方式
function 學(xué)生(學(xué)號) { this.學(xué)號 = 學(xué)號 } 學(xué)生.prototype.年級 = "高一" 學(xué)生.prototype.所選方向 = "理科班" 學(xué)生.prototype.上傳資料 = function () {/*上傳資料的代碼*/} var 學(xué)生們 = [] for (var i = 0; i < 1000; i++) { 學(xué)生們.push(new 學(xué)生(i)) } // 出現(xiàn)constructor屬性 console.log(學(xué)生.prototype) // {年級: "高一", 所選方向: "理科班", 上傳資料: ?, constructor: ?}總結(jié) new的本質(zhì)
new的本質(zhì)其實就是一個語法糖,目的就是為了幫我們省代碼
new的作用創(chuàng)立一個臨時對象,臨時對象指向類的this
把實例__proto__綁定到類的prototype
return臨時對象(也就是this)
關(guān)于new的語法糖var a = {} 是 var a = new Object()的語法糖 var a = [] 是 var a = new Array()的語法糖 var a = funciton(){} 是 var a = new Function()的語法糖參考
new運算符
JS 的 new 到底是干什么的?
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/107488.html
摘要:是什么這個單詞是一個代詞,所以應(yīng)該是指代某些東西搞清楚的關(guān)鍵之處,就是要搞清楚指代了什么那么到底指代了什么呢就像你平時指著一個蘋果說指著一個香蕉說同樣,也會因為情況的不同而不同在中按照常規(guī)理解,的值是什么取決于函數(shù)如何被調(diào)用然而,的值是什么 1. this是什么 this這個單詞是一個代詞,所以this應(yīng)該是 指代某些東西搞清楚this的關(guān)鍵之處,就是要搞清楚this指代了什么 那么t...
摘要:之前有研究過做過假設(shè),在插件列表中,的插件執(zhí)行順序自上而下,一切看起來似乎是沒有任何問題的。再有摘自深入設(shè)計摘自寫的姿勢這兩張圖則應(yīng)該是說明了我之前的假設(shè),插件中的執(zhí)行順序自上而下。先來看看一片來自的這段會不會跟這個有關(guān)呢,我先埋個伏筆。 圖解PostCSS的插件執(zhí)行順序 文章其實是一系列的早就寫完了. 才發(fā)現(xiàn)忘了發(fā)在SegmentFault上面, 最早發(fā)布于https://gitee...
摘要:今日份重點命名規(guī)范注釋關(guān)鍵字關(guān)鍵字總結(jié)命名規(guī)范規(guī)范的包名名字管理是所有編程語言都必須重視的一個問題。比如說百度,其域名為,那么其對應(yīng)的應(yīng)用的包名前綴就應(yīng)該為。是誰這么大牌總結(jié)本文主要介紹了中的命名規(guī)范注解關(guān)鍵字關(guān)鍵字等內(nèi)容。 歡迎關(guān)注我的微信公眾號,共同打牢Java的基礎(chǔ),向著遠方進擊 showImg(https://segmentfault.com/img/bVboaBO?w=129...
摘要:構(gòu)造函數(shù)定義偵探類作為例子。里的既是類的定義,也是構(gòu)造函數(shù)。在構(gòu)造函數(shù)中定義的實例方法和屬性在每一個實例中都會保留一份,而在原型中定義的實例方法和屬性是全部實例只有一份。 無論React還是RN都已經(jīng)邁入了ES6的時代,甚至憑借Babel的支持都進入了ES7。ES6內(nèi)容很多,本文主要講解類相關(guān)的內(nèi)容。 構(gòu)造函數(shù) 定義偵探類作為例子。 ES5的類是如何定義的。 function ES5D...
閱讀 779·2021-10-09 09:58
閱讀 644·2021-08-27 16:24
閱讀 1727·2019-08-30 14:15
閱讀 2387·2019-08-30 11:04
閱讀 2073·2019-08-29 18:43
閱讀 2171·2019-08-29 15:20
閱讀 2720·2019-08-26 12:20
閱讀 1619·2019-08-26 11:44