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