这三个函数都是定义在函数原型对象上的方法,其主要的用途是改变this
的指向,并且调用函数,但是bind
会返回一个改变bind
后的函数。下面我们将详细聊一下三个函数的作用,以及其内部实现。
一、call和apply
(1)、传入参数不同
call
函数可以传入的参数没有限制,第一个参数为this
指向的值,第二个参数一直到最后一个参数都是传入原函数的参数。apply
需要传入两个参数,第一个参数为this
指向的对象,第二个参数是需要传入原函数的参数,是一个数组或者伪数组。
(2)、当第一个参数为null
对于call和apply函数,如果第一个参数为null,那么该函数指向默认宿主对象,在浏览器中会指向window对象。
//在node环境下
function foo(a, b) {
console.log(this)
}
foo.call(null, 10, 20) //global
//在浏览器环境中
foo.call(null, 10, 20) //window
在严格模式下,其中的this都指向null。
function foo(a, b) {
"use strict"
console.log(this)
}
foo.call(null) //null
(3)、
有时候我们使用call,apply其目的不只是改变this,而是调用对象上面的方法,此时我们传入null,就可以表示一个具体的对象。
let nums = Math.max.apply(null, [12,34,56,2,11])
console.log(nums) //56
二、手动实现call函数
//手动实现call
Function.prototype.myCall = function (obj, ...array) {
let fn = this
let thisArg = (obj === undefined || obj === null) ? window : Object(obj)
array = Array.isArray(array) ? array : []
thisArg.fn = fn
let result = thisArg.fn(...array)
delete thisArg.fn
return result
}
三、手动实现apply函数
//手动实现apply
Function.prototype.myApply = function (obj, array) {
let fn = this
let thisArg = (obj === undefined || obj === null) ? window : Object(obj)
thisArg.fn = fn
array = Array.isArray(array) ? array : []
let result = thisArg.fn(...array)
delete thisArg.fn
return result
}
四、手动实现bind函数
bind
返回得是一个函数,就是将this
改变后的函数。
Function.prototype.myBind = function (obj, ...arg1) {
let fn = this
let thisArg = (obj === undefined || obj === null) ? window : Object(obj)
function proxyFn(...arg2) {
thisArg.fn = fn
let arg3 = [...arg1, ...arg2]
let result = thisArg.fn(...arg3)
delete thisArg.fn
return result
}
return proxyFn
}
五、arguments的应用
arguments
是一个伪数组,但是有时候我们需要使用数组的方法,在ES6
之前我们可以使用call
方法来调用,但是在ES6
之后我们可以使用Array.from
来将其转换为数组。