前端 P5 最基本應該掌握的程式碼實現
前景
疫情無情人有情,在去年經歷網際網路一系列的風波之後,我相信大家有很多的小夥伴想在今年金三銀四的面試季中為自己的未來找一個好一點的公司。那麼今天我們來講解一下身為 P5 工程師需要知道的一些原理及其如何親自手寫出它的實現過程,有可能我們日常開發業務的時候用不上這些自己寫的方法,但是我們我們對原理一無所知,那麼在面試的時候一旦被深挖那麼可能離自己心念的公司就會又遠一步。
模式 call
- 第一個引數為 null或者 undefined 時,this 指向全域性物件 window,值為原始值的指向改原始值的自動包裝物件,如 String、number、boolean
- 為了避免函式名與上下問(context)的屬性發生衝突,使用 Symbol 型別作為唯一值
- 將函式作為傳入的上下文(context)屬性執行
- 函式執行完後刪除改屬性
- 返回執行結果
Function.prototype.myCall = function(context,...args){
context = (context ?? window) || new Object(context);
const key = Symbol();
context[key] = this;
const result = context[key](...args);
delete context[key];
return result;
}
模式 apply
- 前部分與call一樣
- 第二個引數可以不傳,但型別必須為陣列或者類陣列
Function.prototype.myApply = function(context) {
context = (context ?? window) || new Object(context)
const key = Symbol()
const args = arguments[1]
context[key] = this
let result
if(args) {
result = context[key](...args)
} else {
result = context[key]
}
delete context[key]
return result
}
模式 bind
- 使用 call / apply 指定 this
- 返回一個繫結函式
- 當返回的繫結函式作為建構函式被new呼叫,繫結的上下文指向例項物件
- 設定繫結函式的prototype 為原函式的prototype
Function.prototype.myBind = function(context, ...args) {
const fn = this
const bindFn = function (...newFnArgs) {
fn.call(
this instanceof bindFn ? this : context,
...args, ...newFnArgs
)
}
bindFn.prototype = Object.create(fn.prototype)
return bindFn
}
深複製
- 判斷型別是否為原始型別,如果是,無需複製直接返回
- 為避免出現迴圈引用,複製物件時先判斷儲存空間中是否存在當前物件,如果有就直接返回
- 開闢一個儲存空間,來儲存當前物件和複製物件的對應關係
- 對引用型別遞迴複製直到屬性為原始型別
const deepClone = (target, cache = new WeakMap()) => {
if(target === null || typeof target !== 'object') {
return target
}
if(cache.get(target)) {
return target
}
const copy = Array.isArray(target) ? [] : {}
cache.set(target, copy)
Object.keys(target).forEach(key => copy[key] = deepClone(obj[key], cache))
return copy
}
函式防抖
- this繼承自父級上下文,指向觸發事件的目標元素
- 事件被觸發時,傳入event物件
- 傳入leading引數,判斷是否可以立即執行回撥函式,不必要等到事件停止觸發後才開始執行
- 回撥函式可以有返回值,需要返回執行結果
const debounce = (fn, wait = 300, leading = true) => {
let timerId, result
return function(...args) {
timerId && clearTimeout(timerId)
if (leading) {
if (!timerId) result = fn.apply(this, args)
timerId = setTimeout(() => timerId = null, wait)
} else {
timerId = setTimeout(() => result = fn.apply(this, args), wait)
}
return result
}
}
函式節流(定時器)
函式停止觸發後 n妙後開始執行,停止觸發後繼續執行一次事件
const throttle = (fn, wait = 300) => {
let timerId
return function(...args) {
if(!timerId) {
timerId = setTimeout(() => {
timerId = null
return result = fn.apply(this, ...args)
}, wait)
}
}
}
函式節流(時間戳)
函式觸發後立刻執行,停止觸發後不在執行事件
const throttle = (fn, wait = 300) => {
let prev = 0
let result
return function(...args) {
let now = +new Date()
if(now - prev > wait) {
prev = now
return result = fn.apply(this, ...args)
}
}
}
ES6版繼承
ES5的繼承,實質是先創造子類的例項物件,然後將再將父類的方法新增到this上。ES6的繼承,先創造父類的例項物件(所以必須先呼叫super方法,然後再用子類的建構函式修改this。
class Super { constructor(foo) { this.foo = foo } printFoo() { console.log(this.foo) } } class Sub extends Super { constructor(foo, bar) { super(foo) this.bar = bar } }js
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/3137/viewspace-2824845/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 前端應該掌握的nginx知識前端Nginx
- 前端css實現最基本的時間軸前端CSS
- 一個自信的前端應該掌握的CDN操作前端
- 前端都應該要掌握的防抖和節流前端
- 程式設計師 應該掌握的英語詞彙程式設計師
- PHP程式設計師應該掌握的10項技能PHP程式設計師
- .net程式設計師應該掌握的常用類庫程式設計師
- 我們應該如何編寫高質量的前端程式碼前端
- 程式設計師應該掌握的10個搜尋技巧程式設計師
- Java程式設計師應該掌握的三種語言Java程式設計師
- Java之列舉, 程式設計師應該掌握的開發技巧“簡潔易懂又安全的程式碼”Java程式設計師
- 新手應該掌握的Linux命令(轉)Linux
- 前端應該知道的GraphQL前端
- 一名合格的前端開發工程師應該掌握的8個技能前端工程師
- 熟練Java的程式設計師應該掌握的知識技能Java程式設計師
- 一個PHP程式設計師應該掌握的10項技能!【更新】PHP程式設計師
- Android 開發應該掌握的 Proguard 技巧Android
- Android開發應該掌握的Proguard技巧Android
- 學習 MySQL 應該掌握的 6 個技巧MySql
- web前端換行程式碼的幾種實現方式!Web前端行程
- 前端應該瞭解的PWA前端
- 一行程式碼實現微前端行程前端
- 結合自己經歷聊聊注重實效的程式設計師應該掌握的幾個原則程式設計師
- 後端開發應該掌握的Redis基礎後端Redis
- ORACLE DBA應該掌握的9個免費工具Oracle
- 開發者應該掌握的3個發行步驟
- 你應該掌握的七種迴歸技術
- 寫程式碼之前應該做的幾件事
- 五種應該避免的程式碼註釋
- javascript實現的iframe高度自適應程式碼JavaScript
- MVP設計模式應該這樣掌握MVP設計模式
- iOS 工程師應該掌握哪些技能?iOS工程師
- 前端應該知道的web登入前端Web
- 你應該知道的前端--渲染原理前端
- 你應該知道的前端--儲存前端
- 你應該知道的前端——快取前端快取
- 【翻譯】前端開發者應掌握的基本知識前端
- 遊戲陪玩原始碼的移動端適配,應該如何實現?遊戲原始碼