日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 前端技术 > javascript >内容正文

javascript

面试官问:能否模拟实现JS的new操作符(高频考点)

發(fā)布時(shí)間:2023/12/9 javascript 47 豆豆
生活随笔 收集整理的這篇文章主要介紹了 面试官问:能否模拟实现JS的new操作符(高频考点) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

可以點(diǎn)擊上方的話題JS基礎(chǔ)系列,查看往期文章
這篇文章寫于2018年11月05日,new模擬實(shí)現(xiàn),Object.create是面試高頻考點(diǎn),之前發(fā)布在掘金有近2萬(wàn)人閱讀,現(xiàn)在發(fā)布到公眾號(hào)聲明原創(chuàng)。

1. 前言

這是面試官問(wèn)系列的第一篇,旨在幫助讀者提升JS基礎(chǔ)知識(shí),包含new、call、apply、this、繼承相關(guān)知識(shí)。
面試官問(wèn)系列文章如下:感興趣的讀者可以點(diǎn)擊閱讀。
1.面試官問(wèn):能否模擬實(shí)現(xiàn)JS的new操作符
2.面試官問(wèn):能否模擬實(shí)現(xiàn)JS的bind方法
3.面試官問(wèn):能否模擬實(shí)現(xiàn)JS的call和apply方法
4.面試官問(wèn):JS的this指向
5.面試官問(wèn):JS的繼承

用過(guò)Vuejs的同學(xué)都知道,需要用new操作符來(lái)實(shí)例化。

new?Vue({el:?'#app',mounted(){}, });

那么面試官可能會(huì)問(wèn)是否想過(guò)new到底做了什么,怎么模擬實(shí)現(xiàn)呢。

附上之前寫文章寫過(guò)的一段話:已經(jīng)有很多模擬實(shí)現(xiàn)new操作符的文章,為什么自己還要寫一遍呢。學(xué)習(xí)就好比是座大山,人們沿著不同的路登山,分享著自己看到的風(fēng)景。你不一定能看到別人看到的風(fēng)景,體會(huì)到別人的心情。只有自己去登山,才能看到不一樣的風(fēng)景,體會(huì)才更加深刻。

2. new 做了什么

先看簡(jiǎn)單例子1

//?例子1 function?Student(){ } var?student?=?new?Student(); console.log(student);?//?{} // student 是一個(gè)對(duì)象。 console.log(Object.prototype.toString.call(student));?//?[object?Object] //?我們知道平時(shí)聲明對(duì)象也可以用new?Object();?只是看起來(lái)更復(fù)雜 //?順便提一下?`new?Object`(不推薦)和Object()也是一樣的效果 //?可以猜測(cè)內(nèi)部做了一次判斷,用new調(diào)用 /**?if?(!(this?instanceof?Object))?{ *????return?new?Object(); *??} */ var?obj?=?new?Object(); console.log(obj)?//?{} console.log(Object.prototype.toString.call(student));?//?[object?Object]typeof?Student?===?'function'?//?true typeof?Object?===?'function'?//?true

從這里例子中,我們可以看出:一個(gè)函數(shù)用new操作符來(lái)調(diào)用后,生成了一個(gè)全新的對(duì)象。而且Student和Object都是函數(shù),只不過(guò)Student是我們自定義的,Object是JS本身就內(nèi)置的。再來(lái)看下控制臺(tái)輸出圖,感興趣的讀者可以在控制臺(tái)試試。

例子1 控制臺(tái)輸出圖

與new Object() 生成的對(duì)象不同的是new Student()生成的對(duì)象中間還嵌套了一層__proto__,它的constructor是Student這個(gè)函數(shù)。

//?也就是說(shuō): student.constructor?===?Student; Student.prototype.constructor?===?Student;

2.1 小結(jié)1:從這個(gè)簡(jiǎn)單例子來(lái)看,new操作符做了兩件事:

  • 創(chuàng)建了一個(gè)全新的對(duì)象。

  • 這個(gè)對(duì)象會(huì)被執(zhí)行[[Prototype]](也就是__proto__)鏈接。

  • 接下來(lái)我們?cè)賮?lái)看升級(jí)版的例子2

    //?例子2 function?Student(name){console.log('賦值前-this',?this);?//?{}this.name?=?name;console.log('賦值后-this',?this);?//?{name:?'若川'} } var?student?=?new?Student('若川'); console.log(student);?//?{name:?'若川'}

    由此可以看出:這里Student函數(shù)中的this指向new Student()生成的對(duì)象student。

    2.2 小結(jié)2:從這個(gè)例子來(lái)看,new操作符又做了一件事:

  • 生成的新對(duì)象會(huì)綁定到函數(shù)調(diào)用的this。

  • 接下來(lái)繼續(xù)看升級(jí)版例子3

    //?例子3 function?Student(name){this.name?=?name;//?this.doSth(); } Student.prototype.doSth?=?function()?{console.log(this.name); }; var?student1?=?new?Student('若'); var?student2?=?new?Student('川'); console.log(student1,?student1.doSth());?//?{name:?'若'}?'若' console.log(student2,?student2.doSth());?//?{name:?'川'}?'川' student1.__proto__?===?Student.prototype;?//?true student2.__proto__?===?Student.prototype;?//?true //?__proto__?是瀏覽器實(shí)現(xiàn)的查看原型方案。 //?用ES5 則是: Object.getPrototypeOf(student1)?===?Student.prototype;?//?true Object.getPrototypeOf(student2)?===?Student.prototype;?//?true

    例子3 控制臺(tái)輸出圖

    關(guān)于JS的原型關(guān)系我之前看到這張圖,覺(jué)得很不錯(cuò),分享給大家。

    2.3 小結(jié)3:這個(gè)例子3再一次驗(yàn)證了小結(jié)1中的第2點(diǎn)。也就是這個(gè)對(duì)象會(huì)被執(zhí)行[[Prototype]](也就是__proto__)鏈接。并且通過(guò)new Student()創(chuàng)建的每個(gè)對(duì)象將最終被[[Prototype]]鏈接到這個(gè)Student.protytype對(duì)象上。

    細(xì)心的同學(xué)可能會(huì)發(fā)現(xiàn)這三個(gè)例子中的函數(shù)都沒(méi)有返回值。那么有返回值會(huì)是怎樣的情形呢。那么接下來(lái)請(qǐng)看例子4

    //?例子4 function?Student(name){this.name?=?name;//?Null(空)?null//?Undefined(未定義)?undefined//?Number(數(shù)字)?1//?String(字符串)'1'//?Boolean(布爾)?true//?Symbol(符號(hào))(第六版新增)?symbol//?Object(對(duì)象)?{}//?Function(函數(shù))?function(){}//?Array(數(shù)組)?[]//?Date(日期)?new?Date()//?RegExp(正則表達(dá)式)/a///?Error?(錯(cuò)誤)?new?Error()//?return?/a/; } var?student?=?new?Student('若川'); console.log(student);?{name:?'若川'}

    我測(cè)試這七種類型后MDN JavaScript類型,得出的結(jié)果是:前面六種基本類型都會(huì)正常返回{name: '若川'},后面的Object(包含F(xiàn)unctoin, Array, Date, RegExg, Error)都會(huì)直接返回這些值。

    2.4 由此得出 小結(jié)4:

  • 如果函數(shù)沒(méi)有返回對(duì)象類型Object(包含F(xiàn)unctoin, Array, Date, RegExg, Error),那么new表達(dá)式中的函數(shù)調(diào)用會(huì)自動(dòng)返回這個(gè)新的對(duì)象。

  • 結(jié)合這些小結(jié),整理在一起就是:

  • 創(chuàng)建了一個(gè)全新的對(duì)象。

  • 這個(gè)對(duì)象會(huì)被執(zhí)行[[Prototype]](也就是__proto__)鏈接。

  • 生成的新對(duì)象會(huì)綁定到函數(shù)調(diào)用的this。

  • 通過(guò)new創(chuàng)建的每個(gè)對(duì)象將最終被[[Prototype]]鏈接到這個(gè)函數(shù)的prototype對(duì)象上。

  • 如果函數(shù)沒(méi)有返回對(duì)象類型Object(包含F(xiàn)unctoin, Array, Date, RegExg, Error),那么new表達(dá)式中的函數(shù)調(diào)用會(huì)自動(dòng)返回這個(gè)新的對(duì)象。

  • 3. new 模擬實(shí)現(xiàn)

    知道了這些現(xiàn)象,我們就可以模擬實(shí)現(xiàn)new操作符。直接貼出代碼和注釋

    /***?模擬實(shí)現(xiàn)?new?操作符*?@param??{Function}?ctor?[構(gòu)造函數(shù)]*?@return?{Object|Function|Regex|Date|Error}??????[返回結(jié)果]*/ function?newOperator(ctor){if(typeof?ctor?!==?'function'){throw?'newOperator?function?the?first?param?must?be?a?function';}//?ES6?new.target?是指向構(gòu)造函數(shù)newOperator.target?=?ctor;//?1.創(chuàng)建一個(gè)全新的對(duì)象,//?2.并且執(zhí)行[[Prototype]]鏈接// 4.通過(guò)`new`創(chuàng)建的每個(gè)對(duì)象將最終被`[[Prototype]]`鏈接到這個(gè)函數(shù)的`prototype`對(duì)象上。var?newObj?=?Object.create(ctor.prototype);//?ES5?arguments轉(zhuǎn)成數(shù)組?當(dāng)然也可以用ES6?[...arguments],?Aarry.from(arguments);//?除去ctor構(gòu)造函數(shù)的其余參數(shù)var?argsArr?=?[].slice.call(arguments,?1);// 3.生成的新對(duì)象會(huì)綁定到函數(shù)調(diào)用的`this`。//?獲取到ctor函數(shù)返回結(jié)果var?ctorReturnResult?=?ctor.apply(newObj,?argsArr);//?小結(jié)4?中這些類型中合并起來(lái)只有Object和Function兩種類型?typeof?null?也是'object'所以要不等于null,排除nullvar?isObject?=?typeof?ctorReturnResult?===?'object'?&&?ctorReturnResult?!==?null;var?isFunction?=?typeof?ctorReturnResult?===?'function';if(isObject?||?isFunction){return?ctorReturnResult;}// 5.如果函數(shù)沒(méi)有返回對(duì)象類型`Object`(包含`Functoin`, `Array`, `Date`, `RegExg`, `Error`),那么`new`表達(dá)式中的函數(shù)調(diào)用會(huì)自動(dòng)返回這個(gè)新的對(duì)象。return?newObj; }

    最后用模擬實(shí)現(xiàn)的newOperator函數(shù)驗(yàn)證下之前的例子3

    //?例子3?多加一個(gè)參數(shù) function?Student(name,?age){this.name?=?name;this.age?=?age;//?this.doSth();//?return?Error(); } Student.prototype.doSth?=?function()?{console.log(this.name); }; var?student1?=?newOperator(Student,?'若',?18); var?student2?=?newOperator(Student,?'川',?18); //?var?student1?=?new?Student('若'); //?var?student2?=?new?Student('川'); console.log(student1,?student1.doSth());?//?{name:?'若'}?'若' console.log(student2,?student2.doSth());?//?{name:?'川'}?'川'student1.__proto__?===?Student.prototype;?//?true student2.__proto__?===?Student.prototype;?//?true //?__proto__?是瀏覽器實(shí)現(xiàn)的查看原型方案。 //?用ES5 則是: Object.getPrototypeOf(student1)?===?Student.prototype;?//?true Object.getPrototypeOf(student2)?===?Student.prototype;?//?true

    可以看出,很符合new操作符。讀者發(fā)現(xiàn)有不妥或可改善之處,歡迎指出。回顧這個(gè)模擬new函數(shù)newOperator實(shí)現(xiàn),最大的功臣當(dāng)屬于Object.create()這個(gè)ES5提供的API。

    4. Object.create() 用法舉例

    我之前整理的一篇文章中也有講過(guò),可以翻看JavaScript 對(duì)象所有API解析

    MDN Object.create()

    Object.create(proto, [propertiesObject])方法創(chuàng)建一個(gè)新對(duì)象,使用現(xiàn)有的對(duì)象來(lái)提供新創(chuàng)建的對(duì)象的__proto__。它接收兩個(gè)參數(shù),不過(guò)第二個(gè)可選參數(shù)是屬性描述符(不常用,默認(rèn)是undefined)。

    var?anotherObject?=?{name:?'若川' }; var?myObject?=?Object.create(anotherObject,?{age:?{value:18,}, }); //?獲得它的原型 Object.getPrototypeOf(anotherObject)?===?Object.prototype;?//?true?說(shuō)明anotherObject的原型是Object.prototype Object.getPrototypeOf(myObject);?//?{name:?"若川"}?//?說(shuō)明myObject的原型是{name:?"若川"} myObject.hasOwnProperty('name');?// false;?說(shuō)明name是原型上的。 myObject.hasOwnProperty('age');?//?true?說(shuō)明age是自身的 myObject.name;?//?'若川' myObject.age;?//?18;

    對(duì)于不支持ES5的瀏覽器,MDN上提供了ployfill方案。

    if?(typeof?Object.create?!==?"function")?{Object.create?=?function?(proto,?propertiesObject)?{if?(typeof?proto?!==?'object'?&&?typeof?proto?!==?'function')?{throw?new?TypeError('Object?prototype?may?only?be?an?Object:?'?+?proto);}?else?if?(proto?===?null)?{throw?new?Error("This?browser's?implementation?of?Object.create?is?a?shim?and?doesn't?support?'null'?as?the?first?argument.");}if?(typeof?propertiesObject?!=?'undefined')?throw?new?Error("This?browser's?implementation?of?Object.create?is?a?shim?and?doesn't?support?a?second?argument.");function?F()?{}F.prototype?=?proto;return?new?F();}; }

    到此,文章就基本寫完了。感謝讀者看到這里。

    5. 最后總結(jié)一下:

  • new做了什么:

  • 創(chuàng)建了一個(gè)全新的對(duì)象。

  • 這個(gè)對(duì)象會(huì)被執(zhí)行[[Prototype]](也就是__proto__)鏈接。

  • 生成的新對(duì)象會(huì)綁定到函數(shù)調(diào)用的this。

  • 通過(guò)new創(chuàng)建的每個(gè)對(duì)象將最終被[[Prototype]]鏈接到這個(gè)函數(shù)的prototype對(duì)象上。

  • 如果函數(shù)沒(méi)有返回對(duì)象類型Object(包含F(xiàn)unctoin, Array, Date, RegExg, Error),那么new表達(dá)式中的函數(shù)調(diào)用會(huì)自動(dòng)返回這個(gè)新的對(duì)象。

  • 怎么模擬實(shí)現(xiàn)

  • //?去除了注釋 function?newOperator(ctor){if(typeof?ctor?!==?'function'){throw?'newOperator?function?the?first?param?must?be?a?function';}newOperator.target?=?ctor;var?newObj?=?Object.create(ctor.prototype);var?argsArr?=?[].slice.call(arguments,?1);var?ctorReturnResult?=?ctor.apply(newObj,?argsArr);var?isObject?=?typeof?ctorReturnResult?===?'object'?&&?ctorReturnResult?!==?null;var?isFunction?=?typeof?ctorReturnResult?===?'function';if(isObject?||?isFunction){return?ctorReturnResult;}return?newObj; }

    讀者發(fā)現(xiàn)有不妥或可改善之處,歡迎指出。另外覺(jué)得寫得不錯(cuò),可以點(diǎn)個(gè)贊,也是對(duì)我的一種支持。

    推薦閱讀

    我在阿里招前端,我該怎么幫你?(現(xiàn)在還可以加模擬面試群)
    如何拿下阿里巴巴 P6 的前端 Offer
    如何準(zhǔn)備阿里P6/P7前端面試--項(xiàng)目經(jīng)歷準(zhǔn)備篇
    大廠面試官常問(wèn)的亮點(diǎn),該如何做出?
    如何從初級(jí)到專家(P4-P7)打破成長(zhǎng)瓶頸和有效突破
    若川知乎問(wèn)答:2年前端經(jīng)驗(yàn),做的項(xiàng)目沒(méi)什么技術(shù)含量,怎么辦?
    若川知乎高贊:有哪些必看的 JS庫(kù)?

    末尾

    你好,我是若川,江湖人稱菜如若川,歷時(shí)一年只寫了一個(gè)學(xué)習(xí)源碼整體架構(gòu)系列~(點(diǎn)擊藍(lán)字了解我)

  • 關(guān)注若川視野,回復(fù)"pdf" 領(lǐng)取優(yōu)質(zhì)前端書籍pdf,回復(fù)"1",可加群長(zhǎng)期交流學(xué)習(xí)

  • 我的博客地址:https://lxchuan12.gitee.io?歡迎收藏

  • 覺(jué)得文章不錯(cuò),可以點(diǎn)個(gè)在看呀^_^另外歡迎留言交流~

  • 精選前端好文,伴你不斷成長(zhǎng)

    我是若川歡迎關(guān)注!可點(diǎn)擊

    小提醒:若川視野公眾號(hào)面試、源碼等文章合集在菜單欄中間【源碼精選】按鈕,歡迎點(diǎn)擊閱讀,也可以星標(biāo)我的公眾號(hào),便于查找

    總結(jié)

    以上是生活随笔為你收集整理的面试官问:能否模拟实现JS的new操作符(高频考点)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。