最近準備初級前端面試,發現有不少手寫實現什麼的,例如什麼手寫實現bind,promise。手寫ajax,手寫一些算法。
翻閱了不少書籍和博客。javascript
這裏作一個總結改進,算是對我後面大概爲期一個月找工做的準備。html
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; }
簡單的說明:前端
new
以構造函數的形式調用硬綁定函數的狀況:this
這時是應該指向實例對象的。 fBind.prototype = self.prototype&&Object.create(self.prototype)
,同時也能夠用 Object.setPrototypeOf(fBind.prototype,self.prototype)
。
考慮到存在undefined
的狀況,前面加一個判斷self.prototype&&.....
java
apply
的第一個參數,若是考慮到以前的狀況,是不能傳入context
的,這須要作一個判斷。像是下面的狀況node
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
,它指向實例對象自己。es6
後面以這道題爲引線面試官可能會追問:面試
首先拷一個阮神在他es6教程裏的一個寫法。ajax
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); }
更精簡的算法
const feibo= max=>{ let [a,b,i]= [0,1,1] while(i++<=max) { [a,b] = [b,a + b ] console.log(b) } return a }
相對是很是簡單的,感受也不會多問啥,就很少說了。數組
let xhr = new XMLHttpRequest() xhr.open('get', url, true) xhr.onreadystatechange = function(){ if(xhr.readyState === 4){ console.log('請求完成') if(this.status >= 200 &&this.status<300){ conso.log('成功') }else{ consol.log('失敗') } } } xhr.onerror = function(e) { console.log('鏈接失敗') } xhr.send()
大概是這麼個意思就差很少了,順勢可能會問一些狀態碼和狀態值的問題,或者直接問到關於http上面的問題。
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()
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) }
我通常就用這兩種,大部分狀況都能應付了。
[...new Set(array)]
//hash function unique(array) { const object = {} array.map(number=>{ object[number] = true }) return Object.keys(object).map(//.......) }//大概是這樣的意思,寫法根據數組的不一樣可能會有所改變
應該是面試裏面手寫xxx出現頻率最高的題了,不管是筆試仍是面試。
老是讓你手寫實現深拷貝函數。
事實上,js並不能作到真正徹底的標準的深拷貝
因此無論你寫什麼樣的深拷貝函數都會有不適用的地方,這取決於使用的場景和拷貝的對象,若是面試官在這上面鑽研比較深的話,是很難作到完美的。
既然這樣就寫個將就一點的深拷貝吧,面向面試的那種。
function deepClone(item) { return result; }
首先在類型判斷上作一個選擇,通常狀況來講,用new
建立的實例對象用typeof
判斷會出問題的,相比之下instanceof
也不靠譜。這裏面相對比較靠譜的Object.prototype.toString.call(item)
。(這個其實也不兼容到所有狀況和性能要求,可是面向面試代碼可讀性會高一點)。
type = Object.prototype.toString.call(item).slice(8,this.length-1), //[object String],[object Array],[object Object]
bind
,會改變this
指向或影響後續使用call
調用該拷貝的函數,大部分狀況是沒必要要的,這裏就直接賦值吧。因而這裏能夠把基本數據類型和Function
放一塊兒。
fk= ['String','Number','Boolean','Function'].indexOf(type)>-1
dom
對象的拷貝: 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]()
這樣子是否是相對清晰一些了,應付通常的狀況應該差很少了,可是沒考慮循環引用。
這裏給個思路是使用ES6
的WeakMap
,不知道的兄弟能夠看看阮神的ES6博客,爲防止爆棧,我把循環引用直接扔給它,完美拷貝。
就至關於
var wm = new WeakMap() var obj = { name:null } obj.name = obj wm.set(obj,wm.get(obj)) console.log(wm)
如今就須要在開頭檢查一下循環引用,而後直接返回WeakMap對象鍵名爲item參數對象的值
因此最終代碼就是
function deepClone(item,hash = new WeakMap()) { if (!item) return item if (hash.has(item))return hash.get(item); //檢查循環引用 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對象 }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; }
意思就大概是這個意思,固然深拷貝的方法有不少,甚至不必定用到遞歸。面試官總會有找茬的地方的。
我以爲我寫的這個仍是知足我如今找工做的級別要求的。
而後是我用來測試的對象
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
簡單說下大概是這麼一個過程
模擬須要考慮的問題
obj
原型鏈是沒有上一級的,即不存在與其餘任何對象之間的聯繫,雖然在這裏面沒多少區別:var obj = Object.create(null),
this
指向這個空對象:let rt = Constructor.apply(obj, arguments);
Object.setPrototypeOf(obj, Constructor.prototype);
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; }
<br/>
<br/>
快排
:代碼精簡了一點
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)) }
這期間會不斷更新並修改,這裏面的手寫實現您若是有更好的寫法或者新的思路,也但願能夠說明交流。最後謝謝大佬些的觀看。