重學前端:原生實現 call、apply、bind 函數。

目錄

  • 這三個函數的 特點
  • call & apply & bind第一個參數,到底傳的什麼
  • 這三個函數實際解決的是什麼問題?

先看看怎麼調用

let obj = {
	arr: [1, 6, 3, 5],
	getArr: function() {
		console.log(
			this.arr
		)
	}
}


// 1.call
Math.max.call(this, ...obj.arr)  // output 6

// 2.apply
Math.max.apply(this, obj.arr)     // output 6

// 3.bind
let getArr = obj.getArr;
getArr()    // undefined
getArr =  getArr.bind(obj)
getArr()    // [1, 6, 3, 5]

特點

  1. call
    第一個參數是當前上下文,而call 函數的實參 是隻能一個一個傳入的。
  2. apply
    第一個參數爲當前上下文,而apply函數 是可以直接傳入數組的
  3. bind
    將上下文綁定到傳入的參數。

實現

call

Function.prototype.mycall = function(context ) {
	if (typeof this != 'function') {
        throw new TypeError('this is not a function')
    }
	// 位置1
    context = context || window
    // 位置2
    context.fn = this
    let arg = [...arguments].slice(1);
    let res = context.fn(...arg)
    delete context.fn
    return res
}
  1. call apply bind第一個傳入的都是當前上下文
  2. 位置1:將上下文傳入, 如果傳入 null則指向window
  3. 位置2:當我們調用 mycall函數時,this指向 .(點)前的函數,然後賦值給 context
  4. 然後通過 arguments拿去傳入參數
  5. 調用 記得用完刪掉就行。

apply

實現思路和 call函數一樣,只是參數 一個是單個,一個是數組。

Function.prototype.myapply = function(context) {
    if (typeof this != 'function') {
        throw new TypeError('this is not a function')
    }
    context = context || window
    context.fn = this
    let result
    if (arguments[1]) {
       result = context.fn(...arguments[1])
    } else {
        result = context.fn()
    }
    delete context.fn
    return result
}

bind

最重要的一點 就是 將上下文 指向傳入的參數中

Function.prototype.mybind = function(context) {
    if (typeof this != 'function') {
        throw new TypeError('this is not a func')
    }
    let _this = this
    let arg = [...arguments].slice(1)
    return function F() {
        return _this.apply(context, arg.concat(...arguments))
    }
}

var person = {
    name: 'Gavin',
    getName() {
        console.log(this.name)
        return this.name
    }
}
person.getName() // Gavin


var getName = person.getName
getName()  // undefined
var Gavin = getName.mybind(person)

console.log(Gavin())  // Gavin
  1. _this指向 .前的 getName函數
  2. 然後 用 apply函數 將 getName函數的上下文指向person(即 context)

實際解決的問題

就是當 當前上下文this指向不是我們想要的時, 就可以使用這三個函數 將 this指向我們想要的結果

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章