# Call Apply Bind

4 min read
Table of Contents

call, apply 和 bind 都是 JavaScript 中用于函数绑定的方法。

Apply 和 Call

Function.prototype.apply 方法调用给定 this 值函数,并将参数作为数组或类数组。

语法:func.apply(thisArg, [argsArray])

Function.prototype.call 方法调用给定的 this 值函数,并分别地提供参数。

语法:func.call(thisArg, arg1, arg2, ...)

两者返回值:指定 this 和参数之后的函数调用结果。

Apply 和 Call 比较

  1. Function.prototype.apply 和 Function.prototype.call 的作用是一样的。
  2. 第一个参数都是要调用函数的母对象,它是调用上下文,在函数体内通过 this 来获得对它的引用。
  3. 从第二参数,apply 接受的是一个参数数组,把它作为参数传给函数。call 接受的是参数列表(不固定长度),然后全部作为参数传给函数。
  4. call 比 apply 的性能好。

关于 this,你可以调用现有的函数,然后分配给不同的对象。通过 apply 或 call 你可以继承别的对象的方法。

var array = ['a', 'b']
var elements = [0, 1, 2]
// 等价于 array.push(elements),相当于 array 继承了 [].push 方法
;[].push.apply(array, elements) // array: ['a', 'b', 0, 1, 2]
var person = {
intro: function (name, company) {
console.log(`I am ${name}, use ${company}`)
},
}
var another = {}
person.intro.call(another, 'ABC', 'javascript') // I am ABC, use javascript
// anthoer 本来没有 intro 方法,通过 call 继承了 person 的 intro 中的方法

apply 可以传入类数组,所以经常与 arugments 参数一起使用。

call 的实现

Function.prototype._call = function (context, ...args) {
// 判断调用者是否为函数,this 就是调用的函数
if (typeof this !== 'function') {
throw new Error('need function')
}
// 生成唯一值用于挂载,后续删除
const fnKey = Symbol()
if (!context) {
context = window
}
context[fnKey] = this
const res = context[fnKey](...args)
delete context[fnKey]
return res
}

Bind

bind 创建一个新函数,该函数在被调用时将 this 指定到提供的值,并在调用新函数时提供其余的参数。 简单的说,就是将函数的 this 绑定到指定的对象中。

语法:let boundFunc = func.bind(thisArg[,arg1[,arg2[, ...]]])

返回值:指定了 this 和参数之后的一个函数副本。

this.x = 9;
const module = {
x: 81,
}
const getX = function() {
return this.x;
}
const boundGetX = getX.bind(module);
getX(); => 9
boundGetX(); => 81

个人觉得,apply,call 和 bind 一个很重要的区别就是返回结果,前两者是调用了函数,返回执行之后的结果。后者是返回一个新的函数。

参考链接


More Posts

# 回流与重绘

7 min read

当渲染树中的元素尺寸,结构或属性发生改变时,需要浏览器重新渲染的过程称为回流( reflow ),而当渲染树中元素样式的改变,并不影响布局时,浏览器重新绘制它的过程称为重绘( repaint )