JS基础——call()、apply()、bind()

100 阅读2分钟

JS基础——call、bind、apply

三者均可用来改变函数绑定的this,使其成为我们指定的对象

  • call()、apply()作用相似
  • 区别是传递参数形式不同,call()传递的是参数列表,apply()传递的是数组
fn.call(thisArg,arg1,arg2,...)
fn.apply(thisArg,[arg1,arg2,...])

thisArg是当前作用域;arg1,arg2...是传递的参数

call() :接收参数是一个参数列表

例子

function sum(num1, num2) {
  return num1 + num2
}

function callSum(num1, num2) {
  return sum.call(this, num1, num2)
}

console.log(callSum(10,10))

call()能扩充函数赖以运行的函数作用域

例子

window.color = 'red'
var o = {color: 'blue'}

function getColor() {
  console.log(this.color)
}

getColor()  // red
getColor.call(this)  // red
getColor.call(window)  // red
getColor.call(o)  // blue

尝试手写一下call()

// 手写call()方法
Function.prototype.myCall = function(thisArg, ...args) {
    thisArg.fn = this              // this指向调用call的对象,即我们要改变this指向的函数
    return thisArg.fn(...args)     // 执行函数并return其执行结果
}
 
// 尝试第一个例子
function sum(num1, num2) {
  return num1 + num2;
}
 
function callSum(num1, num2) {
  return sum.myCall(this, num1, num2);
}
 
console.log(callSum(10, 10)); // 20
 
// 尝试第二个例子
window.color = 'red';
var o = { color: 'blue' };
 
function sayColor() {
  console.log(this.color)
}
 
sayColor();               // red
sayColor.myCall(this);    // red
sayColor.myCall(window);  // red
sayColor.myCall(o);       // blue

call()能进行进一步优化

Function.prototype.myCall = function (thisArg,...args) {
  var fn = Symbol('fn')   // 声明一个唯一属性,防止fn覆盖已存在属性
  thisArg = thisArg || window  // 如果没有传入this,默认指向window对象
  thisArg[fn] = this  // 改变this指向的函数(指向调用call的对象)
  var result = thisArg[fn](...args)  // 执行函数
  delete thisArg[fn]  // 删除定义的fn属性
  return result // 返回执行结果
}

apply() :接收参数是一个数组

对照手写call()写原生apply()

Function.prototype.myApply = function (thisArg, args) {
  var fn = Symbol('fn')
  thisArg = thisArg || window
  var args1 = args ? args : []  // 判断是否传递了参数,未传参,就默认参数为空数组
  thisArg[fn] = this
  var result = thisArg[fn](...args1) // 虽然apply接收的参数形式是数组,但是在调用函数的时候还是要传递展开的数组
  delete thisArg[fn]
  return result
}

bind():创建一个函数实例,会被绑定到传递给bind()的值

window.color = 'red'
var o = {
  color: 'blue'
}
function getColor() {
  console.log(this.color);
}
var colorObject = getColor.bind(o)
colorObject() // blue

可通过apply()/call()实现bind

Function.prototype.myBind = function (rest) {
  var self = this
  var context = rest.shift() // 删除第一个参数,也就是执行环境
  return self.apply(context, [...rest])
}