摘要:最近準(zhǔn)備初級(jí)前端面試,發(fā)現(xiàn)有很多手寫(xiě)實(shí)現(xiàn)什么的,例如什么手寫(xiě)實(shí)現(xiàn),。后面以這道題為引線面試官可能會(huì)追問(wèn)什么是執(zhí)行上下文的判斷,的區(qū)別手寫(xiě)一個(gè)函數(shù)實(shí)現(xiàn)斐波那契數(shù)列首先拷一個(gè)阮神在他教程里的一個(gè)寫(xiě)法。
最近準(zhǔn)備初級(jí)前端面試,發(fā)現(xiàn)有很多手寫(xiě)實(shí)現(xiàn)什么的,例如什么手寫(xiě)實(shí)現(xiàn)bind,promise。手寫(xiě)ajax,手寫(xiě)一些算法。
翻閱了很多書(shū)籍和博客。
這里做一個(gè)總結(jié)改進(jìn),算是對(duì)我后面大概為期一個(gè)月找工作的準(zhǔn)備。
手寫(xiě)實(shí)現(xiàn)bind()Function.prototype._bind = function (context) { var self = this; var args = Array.prototype.slice.call(arguments, 1); var fBind = function () { var bindArgs = Array.prototype.slice.call(arguments); return self.apply(this instanceof fBind ? this : context, args.concat(bindArgs)); } fBind.prototype = self.prototype&&Object.create(self.prototype) return fBind; }
簡(jiǎn)單的說(shuō)明:
這里之所以傳參的時(shí)候需要兩個(gè)數(shù)組,是因?yàn)榭紤]到用new以構(gòu)造函數(shù)的形式調(diào)用硬綁定函數(shù)的情況:this這時(shí)是應(yīng)該指向?qū)嵗龑?duì)象的。
這樣子就需要繼承之前函數(shù)的方法, fBind.prototype = self.prototype&&Object.create(self.prototype)
,同時(shí)也可以用 Object.setPrototypeOf(fBind.prototype,self.prototype)。
考慮到存在undefined的情況,前面加一個(gè)判斷self.prototype&&.....
關(guān)于apply的第一個(gè)參數(shù),如果考慮到之前的情況,是不能傳入context的,這需要做一個(gè)判斷。
像是下面的情況
function Foo(price){ this.price =price this.fn = ()=>{ console.log("hi fn") } console.log(this.name) } Foo.prototype.sayMyName = function(){ console.log(this.name) } var Obj1 = { name:"obj1" } var b =Foo._bind(Obj1) b() //"obj1" var c = new b(1000)//"i am c" c.name = "i am c" c.sayMyName()
這里的this的指向就是c,它指向實(shí)例對(duì)象本身。
后面以這道題為引線面試官可能會(huì)追問(wèn):
什么是執(zhí)行上下文
this的判斷
call,bind的區(qū)別
手寫(xiě)一個(gè)函數(shù)實(shí)現(xiàn)斐波那契數(shù)列首先拷一個(gè)阮神在他es6教程里的一個(gè)寫(xiě)法。
function* fibonacci() { let [prev, curr] = [0, 1]; for (;;) { yield curr; [prev, curr] = [curr, prev + curr]; } } for (let n of fibonacci()) { if (n > 1000) break; console.log(n); }
更精簡(jiǎn)的
const feibo= max=>{ let [a,b,i]= [0,1,1] while(i++<=max) { [a,b] = [b,a + b ] console.log(b) } return a }
相對(duì)是非常簡(jiǎn)單的,感覺(jué)也不會(huì)多問(wèn)啥,就不多說(shuō)了。
手寫(xiě)一個(gè)簡(jiǎn)單的ajaxlet xhr = new XMLHttpRequest() xhr.open("get", url, true) xhr.onreadystatechange = function(){ if(xhr.readyState === 4){ console.log("請(qǐng)求完成") if(this.status >= 200 &&this.status<300){ conso.log("成功") }else{ consol.log("失敗") } } } xhr.onerror = function(e) { console.log("連接失敗") } xhr.send()
大概是這么個(gè)意思就差不多了,順勢(shì)可能會(huì)問(wèn)一些狀態(tài)碼和狀態(tài)值的問(wèn)題,或者直接問(wèn)到關(guān)于http上面的問(wèn)題。
原型繼承function inherit(supertype,subtype){ Object.setPrototypeOf(subtype.prototype,supertype.prototype) subtype.prototype.constructor = subtype } function Car(name,power){ this.name=name this.power = power } Car.prototype.showPower = function(){ console.log(this.power) } function Changan(price,name,power){ this.price = price Car.call(this,name,power) } inherit(Car,Changan) Changan.prototype.showName = function(){ console.log(this.name) } var star = new Changan(100000,"star",500) star.showPower()防抖與節(jié)流
function debounce(fn,duration){ var timer window.clearTimeout(timer) timer = setTimeout(()=>{ fn.call(this) },duration) } function throttle(fn,duration){ let canIRun if(!canIRun)return fn.call(this) canIRun = false setTimeout(()=>{ canIRun = true },duration) }數(shù)組去重
我一般就用這兩種,大部分情況都能應(yīng)付了。
[...new Set(array)]
//hash function unique(array) { const object = {} array.map(number=>{ object[number] = true }) return Object.keys(object).map(//.......) }//大概是這樣的意思,寫(xiě)法根據(jù)數(shù)組的不同可能會(huì)有所改變深拷貝
應(yīng)該是面試?yán)锩?strong>手寫(xiě)xxx出現(xiàn)頻率最高的題了,無(wú)論是筆試還是面試。
總是讓你手寫(xiě)實(shí)現(xiàn)深拷貝函數(shù)。
事實(shí)上,js并不能做到真正完全的標(biāo)準(zhǔn)的深拷貝
所以不管你寫(xiě)什么樣的深拷貝函數(shù)都會(huì)有不適用的地方,這取決于使用的場(chǎng)景和拷貝的對(duì)象,如果面試官在這上面鉆研比較深的話,是很難做到完美的。
既然這樣就寫(xiě)個(gè)將就一點(diǎn)的深拷貝吧,面向面試的那種。
function deepClone(item) { return result; }
首先在類型判斷上做一個(gè)選擇,一般情況來(lái)說(shuō),用new創(chuàng)建的實(shí)例對(duì)象用typeof判斷會(huì)出問(wèn)題的,相比之下instanceof也不靠譜。這里面相對(duì)比較靠譜的Object.prototype.toString.call(item)。(這個(gè)其實(shí)也不兼容到全部情況和性能要求,但是面向面試代碼可讀性會(huì)高一點(diǎn))。
type = Object.prototype.toString.call(item).slice(8,this.length-1), //[object String],[object Array],[object Object]
函數(shù)的拷貝,這里不能使用bind,會(huì)改變this指向或影響后續(xù)使用call調(diào)用該拷貝的函數(shù),大部分情況是不必要的,這里就直接賦值吧。
于是這里可以把基本數(shù)據(jù)類型和Function放一起。
fk= ["String","Number","Boolean","Function"].indexOf(type)>-1
dom對(duì)象的拷貝: result = item.cloneNode(true);
忽略正則
Date,[object Object], [object Array]放到后面的判斷
let other = { //需要遞歸或者其他的操作 Array() { result = [] item.forEach((child, index)=>{ hash.set(item, result); result[index] = deepClone(child,hash) }) }, Date(){ result = new Date(item) }, Object(){ result = {} Reflect.ownKeys(item).forEach(child=>{ hash.set(item, result); result[child] = deepClone(item[child],hash) }) } } other[type]()
這樣子是不是相對(duì)清晰一些了,應(yīng)付一般的情況應(yīng)該差不多了,但是沒(méi)考慮循環(huán)引用。
這里給個(gè)思路是使用ES6的WeakMap,不知道的兄弟可以看看阮神的ES6博客,為防止爆棧,我把循環(huán)引用直接扔給它,完美拷貝。
就相當(dāng)于
var wm = new WeakMap() var obj = { name:null } obj.name = obj wm.set(obj,wm.get(obj)) console.log(wm)
現(xiàn)在就需要在開(kāi)頭檢查一下循環(huán)引用,然后直接返回WeakMap對(duì)象鍵名為item參數(shù)對(duì)象的值
所以最終代碼就是
function deepClone(item,hash = new WeakMap()) { if (!item) return item if (hash.has(item))return hash.get(item); //檢查循環(huán)引用 var result, type = Object.prototype.toString.call(item).slice(8,this.length-1), fk= ["String","Number","Boolean","Function"].indexOf(type)>-1 if(fk){ result = item;//直接賦值 }else if(item.nodeType && typeof item.cloneNode === "function"){ result = item.cloneNode(true); //是否是dom對(duì)象 }else{ let other = { //需要遞歸或者其他的操作 Array() { result = [] item.forEach((child, index)=>{ hash.set(item, result); result[index] = deepClone(child,hash) }) }, Date(){ result = new Date(item) }, Object(){ result = {} Reflect.ownKeys(item).forEach(child=>{ hash.set(item, result); result[child] = deepClone(item[child],hash) }) } } other[type]() } return result; }
意思就大概是這個(gè)意思,當(dāng)然深拷貝的方法有很多,甚至不一定用到遞歸。面試官總會(huì)有找茬的地方的。
我覺(jué)得我寫(xiě)的這個(gè)還是滿足我現(xiàn)在找工作的級(jí)別要求的。
然后是我用來(lái)測(cè)試的對(duì)象
var obj1 = { name:"obj1", one : { a:new Date(), b:new String("1-2"), c:new Array(["this","is",1,{a:23}]), d: function () { if(true){ return "d" } }, e:new Number(15), f:new Boolean(true) }, two(x){ console.log(x+" "+this.name) }, three : [ { a:"this is a", b:document.body, c:{ a:[1,2,3,4,5,[13,[3],true],10], b:{ a:{ a:[1,2,3] }, b:2 } } }, ], four:[1,2] } obj1.name=obj1 obj1.four[3] = obj1 var copy = deepClone(obj1) console.log(copy) copy.two.call(window,"hi")
## new
簡(jiǎn)單說(shuō)下大概是這么一個(gè)過(guò)程
創(chuàng)建一個(gè)空對(duì)象
執(zhí)行傳入的構(gòu)造函數(shù),執(zhí)行過(guò)程中對(duì) this 操作就是對(duì) 這個(gè)空對(duì)象 進(jìn)行操作。
返回這個(gè)空對(duì)象
模擬需要考慮的問(wèn)題
是一個(gè)空對(duì)象,這里面的寫(xiě)法obj原型鏈?zhǔn)菦](méi)有上一級(jí)的,即不存在與其他任何對(duì)象之間的聯(lián)系,雖然在這里面沒(méi)多少區(qū)別:var obj = Object.create(null),
this指向這個(gè)空對(duì)象:let rt = Constructor.apply(obj, arguments);
可以訪問(wèn)構(gòu)造函數(shù)的原型鏈, Object.setPrototypeOf(obj, Constructor.prototype);
如果構(gòu)造函數(shù)有返回值,并且是一個(gè)對(duì)象,那么實(shí)例對(duì)象拿到的就是這個(gè)對(duì)象(應(yīng)該只是值,并不是引用)。所以這里要做個(gè)判斷return typeof rt === "object" ? rt : obj;
最終的代碼
function _new(){ var obj = Object.create(null), Constructor = [].shift.call(arguments); Object.setPrototypeOf(obj, Constructor.prototype); let rt = Constructor.apply(obj, arguments); return rt instanceof Object ? rt : obj; }
快排
:代碼精簡(jiǎn)了一點(diǎn)
function quickSort(arr){ if(arr.length<=1)return arr var index = Math.floor(arr.length/2), number = arr.splice(index,1)[0], left = [], right = []; arr.forEach(item=>{ item<=number?left.push(item):right.push(item) }) return quickSort(left).concat([number],quickSort(right)) }
這期間會(huì)不斷更新并修改,這里面的手寫(xiě)實(shí)現(xiàn)您如果有更好的寫(xiě)法或者新的思路,也希望可以說(shuō)明交流。最后謝謝大佬些的觀看。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/103597.html
摘要:第一天寫(xiě)文章,心里難免有些小激動(dòng),希望能堅(jiān)持下去,有輸出才有更好的輸入。用戶選擇完之后,我會(huì)得到一個(gè)時(shí)間戳的數(shù)組這里呢我們先需要看一下的語(yǔ)法。 第一天寫(xiě)文章,心里難免有些小激動(dòng),希望能堅(jiān)持下去,有輸出才有更好的輸入。 reduce這個(gè)方法最初我是在面試題里看見(jiàn)的有一個(gè)長(zhǎng)度為100的數(shù)組,請(qǐng)以優(yōu)雅的方式求出該數(shù)組的前10個(gè)元素之和?答案如下 var a = [1, 2, 3, 4, 5...
摘要:先說(shuō)下我面試情況,我一共面試了家公司。篇在我面試的眾多公司里,只有同城的面問(wèn)到相關(guān)問(wèn)題,其他公司壓根沒(méi)問(wèn)。我自己回答的是自己開(kāi)發(fā)組件面臨的問(wèn)題。完全不用擔(dān)心對(duì)方到時(shí)候打電話核對(duì)的問(wèn)題。 2019的5月9號(hào),離發(fā)工資還有1天的時(shí)候,我的領(lǐng)導(dǎo)親切把我叫到辦公室跟我說(shuō):阿郭,我們公司要倒閉了,錢(qián)是沒(méi)有的啦,為了不耽誤你,你趕緊出去找工作吧。聽(tīng)到這話,我虎軀一震,這已經(jīng)是第2個(gè)月沒(méi)工資了。 公...
摘要:那既然頻繁出,肯定不能是手撕紅黑樹(shù)我覺(jué)得面試官也多半撕不出來(lái),不撕紅黑樹(shù),那這道題還有點(diǎn)救,慢慢往下看。簡(jiǎn)單說(shuō)來(lái)說(shuō),哈希表由兩個(gè)要素構(gòu)成桶數(shù)組和散列函數(shù)。所謂的哈希沖突,就是不同的經(jīng)過(guò)哈希函數(shù)計(jì)算,落到了同一個(gè)下標(biāo)。快手面試官真的嗎我不信。手寫(xiě)HashMap?這么狠,面試都卷到這種程度了?第一次見(jiàn)到這個(gè)面試題,是在某個(gè)不方便透露姓名的Offer收割機(jī)大佬的文章:這……我當(dāng)時(shí)就麻了,我們都知道...
摘要:前言得益于金三銀四,在最近一段時(shí)間,面試了一些人,但是符合的寥寥無(wú)幾。看到我的面試題自己寫(xiě)的面試題,自己想的答案。聽(tīng)人說(shuō)過(guò)一個(gè)面試套路面試官問(wèn)的問(wèn)題,可能面試官自己都不懂,目的只是為了壓工資,挫士氣。不過(guò)我是為了測(cè)試面試者是不是真的精通。 技術(shù)在不斷的創(chuàng)新,隨著框架,庫(kù),構(gòu)建工具,打包工具,版本控制工具等操作越來(lái)越方便,使用越來(lái)越簡(jiǎn)單。面對(duì)這樣的情況,除了興奮,也要警惕。這些工具使得開(kāi)...
閱讀 3029·2023-04-26 00:32
閱讀 513·2019-08-30 15:52
閱讀 2120·2019-08-30 15:52
閱讀 3364·2019-08-30 15:44
閱讀 3293·2019-08-30 14:09
閱讀 1426·2019-08-29 15:15
閱讀 3406·2019-08-28 18:12
閱讀 1091·2019-08-26 13:55