《前端面試手記》之常考的原始碼實現

2021-09-13 03:47:10 字數 4162 閱讀 5899

? 內容速覽 ?

實現乙個完美的深拷貝函式

基於es5/es6實現雙向繫結

instanceof原理與實現

?檢視全部教程 / 閱讀原文?

來看下call的原生表現形式:

function test(arg1, arg2) 

run.call(, 1, 2)

好了,開始手動實現我們的call2。在實現的過程有個關鍵:

如果乙個函式作為乙個物件的屬性,那麼通過物件的.運算子呼叫此函式,this就是此物件

let obj = 

}obj.test(1, 2)

知道了實現關鍵,下面就是我們模擬的call

function.prototype.call2 = function(context) 

// 預設上下文是window

context = context || window

// 儲存預設的fn

const = context

// 前面講的關鍵,將函式本身作為物件context的屬性呼叫,自動繫結this

context.fn = this

const args = [...arguments].slice(1)

const result = context.fn(...args)

// 恢復預設的fn

context.fn = fn

return result

}// 以下是測試**

function test(arg1, arg2)

test.call2(, 1, 2)

因此,借助es6提供的...運算子,就可以很方便的實現陣列和引數序列的轉化。

if(typeof this !== 'function')

context = context || window

const = context

context.fn = this

let result

if(array.isarray(arguments[1])) else

context.fn = fn

return result

}/**

* 以下是測試**

*/function test(arg1, arg2)

a: 'a',

b: 'b'

}, [1, 2])

bind的實現有點意思,它有兩個特點:

function.prototype.bind2 = function(context) 

const that = this

// 保留之前的引數,為了下面的引數拼接

const args = [...arguments].slice(1)

return function f()

// args.concat(...arguments): 拼接之前和現在的引數

// 注意:arguments是個類array的object, 用解構運算子..., 直接拿值拼接

}}/** * 以下是測試**

*/function test(arg1, arg2)

const test2 = test.bind2(, 1) // 引數 1

test2(2) // 引數 2

實現乙個物件的深拷貝函式,需要考慮物件的元素型別以及對應的解決方案:

/**

* 陣列的深拷貝函式

* @param src

* @param target

*/function clonearr(src, target) else if (typeof item === 'object') ))

} else

} return target

}/**

* 物件的深拷貝實現

* @param src

* @param target

* @return

*/function deepclone(src, target) else if (typeof value === 'object') )

} else

} return target

}

這段**是不是比網上看到的多了很多?因為考慮很周全,請看下面的測試用例:

// 這個物件a是乙個囊括以上所有情況的物件

let a = ,

schools: [,],

arr: [[],

[],

]};let b = {}

deepclone(a, b)

a.jobs.first = 'native'

a.schools[0].name = 'szu'

a.arr[0][0].value = '100'

console.log(a.jobs.first, b.jobs.first) // output: native fe

console.log(a.schools[0], b.schools[0]) // output:

console.log(a.arr[0][0].value, b.arr[0][0].value) // output: 100 1

console.log(array.isarray(a.arr[0])) // output: true

看到測試用例,應該會有人奇怪為什麼最後要輸出array.isarray(a.arr[0])。這主要是因為網上很多實現方法沒有針對array做處理,直接將其當成object,這樣拷貝後雖然值沒問題,但是array的元素會被轉化為object。這顯然是錯誤的做法。

而上面所說的深拷貝函式就解決了這個問題。

要想實現,就要先看看什麼是「雙向資料繫結」,它和「單向資料繫結」有什麼區別?這樣才能知道要實現什麼效果嘛。

雙向繫結:檢視(view)的變化能實時讓資料模型(model)發生變化,而資料的變化也能實時更新到檢視層。

單向資料繫結:只有從資料到檢視這一方向的關係。

值是:

隨著,vue3.0放棄支援了ie瀏覽器。而且proxy相容性越來越好,能支援13種劫持操作。

因此,vue3.0選擇使用proxy來實現雙向資料繫結,而不再使用object.defineproperty

值是:

instanceof是通過原型鏈來進行判斷的,所以只要不斷地通過訪問__proto__,就可以拿到建構函式的原型prototype。直到null停止。

/**

* 判斷left是不是right型別的物件

* @param left

* @param right

* @return

*/function instanceof2(left, right)

if(left === prototype)

left = left.__proto__;

}}/** * 測試**

*/console.log(instanceof2(, array)) // output: true

function test(){}

let test = new test()

console.log(instanceof2(test, test)) // output: true

⭐在github上收藏/訂閱⭐

《前端知識體系》

《設計模式手冊》

《webpack4漸進式教程》

⭐在github上收藏/訂閱⭐

原文

前端面試常考知識點

1.css3的新特性有哪些 點我檢視 css3選擇器 css3邊框與圓角 css3圓角border radius 屬性值由兩個引數值構成 value1 value2,值之間用 分隔,value1代表圓角的水平半徑,value2代表圓角的垂直半徑 盒陰影box shadow 語法 box shadow...

前端面試常考知識點 CSS

前端面試常考知識點 js 點我檢視 css3選擇器 css3邊框與圓角 css3圓角border radius 屬性值由兩個引數值構成 value1 value2,值之間用 分隔,value1代表圓角的水平半徑,value2代表圓角的垂直半徑 盒陰影box shadow 語法 box shadow ...

前端面試常考陣列去重方法

站在巨人的肩膀上,利用set集合的屬性實現去重 function unique arr console.log array.from new set 1 4,5 5 通過定義新陣列來實現陣列去重,可通過陣列的includes 或者indexof方法判斷數值是否屬於新陣列 let a 1 2,2 3,...