摘要:使用指定的參數(shù)調(diào)用構造函數(shù),并將綁定到新創(chuàng)建的對象。由構造函數(shù)返回的對象就是表達式的結果。情況返回以外的基本類型實例中只能訪問到構造函數(shù)中的屬性,和情況完全相反,結果相當于沒有返回值。
定義
new 運算符創(chuàng)建一個用戶定義的對象類型的實例或具有構造函數(shù)的內(nèi)置對象的實例。 ——(來自于MDN)
舉個栗子
function Car(color) { this.color = color; } Car.prototype.start = function() { console.log(this.color + " car start"); } var car = new Car("black"); car.color; // 訪問構造函數(shù)里的屬性 // black car.start(); // 訪問原型里的屬性 // black car start
可以看出 new 創(chuàng)建的實例有以下 2 個特性
1、訪問到構造函數(shù)里的屬性
2、訪問到原型里的屬性
注意點ES6新增 symbol 類型,不可以使用 new Symbol(),因為 symbol 是基本數(shù)據(jù)類型,每個從Symbol()返回的 symbol 值都是唯一的。
Number("123"); // 123 String(123); // "123" Boolean(123); // true Symbol(123); // Symbol(123) new Number("123"); // Number?{123} new String(123); // String?{"123"} new Boolean(true); // Boolean?{true} new Symbol(123); // Symbol is not a constructor模擬實現(xiàn)
當代碼 new Foo(...) 執(zhí)行時,會發(fā)生以下事情:
一個繼承自 Foo.prototype 的新對象被創(chuàng)建。
使用指定的參數(shù)調(diào)用構造函數(shù) Foo ,并將 this 綁定到新創(chuàng)建的對象。new Foo 等同于 new Foo(),也就是沒有指定參數(shù)列表,Foo 不帶任何參數(shù)調(diào)用的情況。
由構造函數(shù)返回的對象就是 new 表達式的結果。如果構造函數(shù)沒有顯式返回一個對象,則使用步驟1創(chuàng)建的對象。
模擬實現(xiàn)第一步new 是關鍵詞,不可以直接覆蓋。這里使用 create 來模擬實現(xiàn) new 的效果。
new 返回一個新對象,通過 obj.__proto__ = Con.prototype 繼承構造函數(shù)的原型,同時通過 Con.apply(obj, arguments)調(diào)用父構造函數(shù)實現(xiàn)繼承,獲取構造函數(shù)上的屬性(【進階3-3期】)。
實現(xiàn)代碼如下
// 第一版 function create() { // 創(chuàng)建一個空的對象 var obj = new Object(), // 獲得構造函數(shù),arguments中去除第一個參數(shù) Con = [].shift.call(arguments); // 鏈接到原型,obj 可以訪問到構造函數(shù)原型中的屬性 obj.__proto__ = Con.prototype; // 綁定 this 實現(xiàn)繼承,obj 可以訪問到構造函數(shù)中的屬性 Con.apply(obj, arguments); // 返回對象 return obj; };
測試一下
// 測試用例 function Car(color) { this.color = color; } Car.prototype.start = function() { console.log(this.color + " car start"); } var car = create(Car, "black"); car.color; // black car.start(); // black car start
完美!
不熟悉 apply / call 的點擊查看:【進階3-3期】深度解析 call 和 apply 原理、使用場景及實現(xiàn)
不熟悉繼承的點擊查看:JavaScript常用八種繼承方案
模擬實現(xiàn)第二步上面的代碼已經(jīng)實現(xiàn)了 80%,現(xiàn)在繼續(xù)優(yōu)化。
構造函數(shù)返回值有如下三種情況:
1、返回一個對象
2、沒有 return,即返回 undefined
3、返回undefined 以外的基本類型
情況1:返回一個對象
function Car(color, name) { this.color = color; return { name: name } } var car = new Car("black", "BMW"); car.color; // undefined car.name; // "BMW"
實例 car 中只能訪問到返回對象中的屬性。
情況2:沒有 return,即返回 undefined
function Car(color, name) { this.color = color; } var car = new Car("black", "BMW"); car.color; // black car.name; // undefined
實例 car 中只能訪問到構造函數(shù)中的屬性,和情況1完全相反。
情況3:返回undefined 以外的基本類型
function Car(color, name) { this.color = color; return "new car"; } var car = new Car("black", "BMW"); car.color; // black car.name; // undefined
實例 car 中只能訪問到構造函數(shù)中的屬性,和情況1完全相反,結果相當于沒有返回值。
所以需要判斷下返回的值是不是一個對象,如果是對象則返回這個對象,不然返回新創(chuàng)建的 obj對象。
所以實現(xiàn)代碼如下:
// 第二版 function create() { // 創(chuàng)建一個空的對象 var obj = new Object(), // 獲得構造函數(shù),arguments中去除第一個參數(shù) Con = [].shift.call(arguments); // 鏈接到原型,obj 可以訪問到構造函數(shù)原型中的屬性 obj.__proto__ = Con.prototype; // 綁定 this 實現(xiàn)繼承,obj 可以訪問到構造函數(shù)中的屬性 var ret = Con.apply(obj, arguments); // 優(yōu)先返回構造函數(shù)返回的對象 return ret instanceof Object ? ret : obj; };【進階3-4期】思考題解
問題:用 JS 實現(xiàn)一個無限累加的函數(shù) add,示例如下:
add(1); // 1 add(1)(2); // 3 add(1)(2)(3); // 6 add(1)(2)(3)(4); // 10 // 以此類推
實現(xiàn):
function add(a) { function sum(b) { // 使用閉包 a = a + b; // 累加 return sum; } sum.toString = function() { // 重寫toString()方法 return a; } return sum; // 返回一個函數(shù) } add(1); // 1 add(1)(2); // 3 add(1)(2)(3); // 6 add(1)(2)(3)(4); // 10
我們知道打印函數(shù)時會自動調(diào)用 toString()方法,函數(shù) add(a) 返回一個閉包 sum(b),函數(shù) sum() 中累加計算 a = a + b,只需要重寫sum.toString()方法返回變量 a 就OK了。
參考JavaScript 深入之 new 的模擬實現(xiàn)進階系列目錄MDN 之 new 運算符
MDN 之 Symbol
javascript 函數(shù) add(1)(2)(3)(4) 實現(xiàn)無限極累加
【進階1期】 調(diào)用堆棧
【進階2期】 作用域閉包
【進階3期】 this全面解析
【進階4期】 深淺拷貝原理
【進階5期】 原型Prototype
【進階6期】 高階函數(shù)
【進階7期】 事件機制
【進階8期】 Event Loop原理
【進階9期】 Promise原理
【進階10期】Async/Await原理
【進階11期】防抖/節(jié)流原理
【進階12期】模塊化詳解
【進階13期】ES6重難點
【進階14期】計算機網(wǎng)絡概述
【進階15期】瀏覽器渲染原理
【進階16期】webpack配置
【進階17期】webpack原理
【進階18期】前端監(jiān)控
【進階19期】跨域和安全
【進階20期】性能優(yōu)化
【進階21期】VirtualDom原理
【進階22期】Diff算法
【進階23期】MVVM雙向綁定
【進階24期】Vuex原理
【進階25期】Redux原理
【進階26期】路由原理
【進階27期】VueRouter源碼解析
【進階28期】ReactRouter源碼解析
交流進階系列文章匯總如下,內(nèi)有優(yōu)質(zhì)前端資料,覺得不錯點個star。
https://github.com/yygmind/blog
我是木易楊,網(wǎng)易高級前端工程師,跟著我每周重點攻克一個前端面試重難點。接下來讓我?guī)阕哌M高級前端的世界,在進階的路上,共勉!
文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://systransis.cn/yun/100734.html
摘要:返回的綁定函數(shù)也能使用操作符創(chuàng)建對象這種行為就像把原函數(shù)當成構造器,提供的值被忽略,同時調(diào)用時的參數(shù)被提供給模擬函數(shù)。 bind() bind() 方法會創(chuàng)建一個新函數(shù),當這個新函數(shù)被調(diào)用時,它的 this 值是傳遞給 bind() 的第一個參數(shù),傳入bind方法的第二個以及以后的參數(shù)加上綁定函數(shù)運行時本身的參數(shù)按照順序作為原函數(shù)的參數(shù)來調(diào)用原函數(shù)。bind返回的綁定函數(shù)也能使用 n...
摘要:之前文章詳細介紹了的使用,不了解的查看進階期。不同的引擎有不同的限制,核心限制在,有些引擎會拋出異常,有些不拋出異常但丟失多余參數(shù)。存儲的對象能動態(tài)增多和減少,并且可以存儲任何值。這邊采用方法來實現(xiàn),拼成一個函數(shù)。 之前文章詳細介紹了 this 的使用,不了解的查看【進階3-1期】。 call() 和 apply() call() 方法調(diào)用一個函數(shù), 其具有一個指定的 this 值和分...
摘要:本期推薦文章類內(nèi)存泄漏及如何避免,由于微信不能訪問外鏈,點擊閱讀原文就可以啦。四種常見的內(nèi)存泄漏劃重點這是個考點意外的全局變量未定義的變量會在全局對象創(chuàng)建一個新變量,如下。因為老版本的是無法檢測節(jié)點與代碼之間的循環(huán)引用,會導致內(nèi)存泄漏。 (關注福利,關注本公眾號回復[資料]領取優(yōu)質(zhì)前端視頻,包括Vue、React、Node源碼和實戰(zhàn)、面試指導) 本周正式開始前端進階的第一期,本周的主題...
摘要:木易楊注意原始類型被包裝為對象木易楊原始類型會被包裝,和會被忽略。木易楊原因在于時,其屬性描述符為不可寫,即。木易楊解決方法也很簡單,使用我們在進階期中介紹的就可以了,使用如下。 引言 上篇文章介紹了賦值、淺拷貝和深拷貝,其中介紹了很多賦值和淺拷貝的相關知識以及兩者區(qū)別,限于篇幅只介紹了一種常用深拷貝方案。 本篇文章會先介紹淺拷貝 Object.assign 的實現(xiàn)原理,然后帶你手動實...
摘要:今天這篇文章我們來看看一道必會面試題,即如何實現(xiàn)一個深拷貝。木易楊注意這里使用上面測試用例測試一下一個簡單的深拷貝就完成了,但是這個實現(xiàn)還存在很多問題。 引言 上篇文章詳細介紹了淺拷貝 Object.assign,并對其進行了模擬實現(xiàn),在實現(xiàn)的過程中,介紹了很多基礎知識。今天這篇文章我們來看看一道必會面試題,即如何實現(xiàn)一個深拷貝。本文會詳細介紹對象、數(shù)組、循環(huán)引用、引用丟失、Symbo...
閱讀 663·2021-11-25 09:43
閱讀 1672·2021-11-18 10:02
閱讀 1052·2021-10-15 09:39
閱讀 1898·2021-10-12 10:18
閱讀 2129·2021-09-22 15:43
閱讀 782·2021-09-22 15:10
閱讀 2093·2019-08-30 15:53
閱讀 998·2019-08-30 13:00