call、apply、bind 的用法、区别及内部原理
  • call/apply 都用于改变调用者(函数)内部 this 的指向
  • bind 用于创建一个函数并绑定函数内部的 this 为传入的值
  • bind 是返回对应函数,便于稍后调用;apply 、call 则是立即调用

call/apply 的简单用法

function test (p1, p2) {
  console.log(this.a + p1 + p2)
}

let obj = { a: 1 }
test.call(obj, 2, 3)
test.apply(obj, [2, 3])

call/apply 的实际应用

数组追加多个元素

let arr = [1, 2]
let tar = [3, 4]
Array.prototype.push.apply(arr, tar)

找出数组最大值

let arr = [8, 2, 6, 9, 5]
let max = Math.max.apply(null, arr)
console.log(max)

验证是否为数组

isArray (obj) { 
    return Object.prototype.toString.call(obj) === '[object Array]'
}

伪数组转换为数组

// 常见的伪数组还有 arguments、NodeList 对象等
Array.prototype.slice.call(document.getElementsByTagName("div"))

bind 的简单用法

function test (p1, p2) {
  console.log(this.x + p1 + p2)
}
let obj = { x: 1 }

test.bind(obj, 2)(3)

bind 的实际应用

绑定 this 的指向

let obj = {
  name: 'johnhan',
  getNameFun: function () {
    return function () {
      return this.name
    }.bind(this)
  }
}

let fun = obj.getNameFun()
console.log(fun())

call/apply 的内部实现原理

将 fun 挂在 obj 上,执行完后再移除

// call
Function.prototype.call = function () {
  let [thisArg, ...args] = [...arguments]
  thisArg = thisArg || window
  thisArg.fn = this
  let result = thisArg.fn(...args)
  delete thisArg.fn
  return result
}

// apply
Function.prototype.apply = function () {
  let [thisArg, args] = [...arguments]
  thisArg = thisArg || window
  thisArg.fn = this
  let result = thisArg.fn(...args)
  delete thisArg.fn
  return result
}

// bind
Function.prototype.bind = function() {
  let [thisArg, ...args] = [...arguments]
  thisArg = thisArg || window
  let _this = this
  return function () {
    return _this.call(thisArg, ...args, ...arguments)
  }
}
除特殊说明外本人博客均属原创,转载请注明出处:http://blog.johnhan.cn/blog_1096.html
京ICP备19044523号-1