1、相同点
call、bind、apply都是为了改变this的指向问题。
2、不同点
2.1:call
非严格模式下
let fn = function(a,b){
console.log(this,a,b)
}
let obj = {
name:'屈小康'
}
fn.call(obj,1,2) // this:obj a:1 b:2
fn.call(1,2) //this:window 1 , 2
fn.call(unll) // this:window undefined undefined
fn.call(undefined) // this:window undefined undefined
严格模式下
"use strict"
let fn = function(a,b){
console.log(this,a,b);
}
let obj = {name:"obj"};
fn.call(obj,1,2); // this:obj a:1 b:2
fn.call(1,2); // this:1 a:2 b=undefined
fn.call(); // this:undefined a:undefined b:undefined
fn.call(null); // this:null a:undefined b:undefined
fn.call(undefined); // this:undefined a:undefined b:undefined
2.2:apply
apply把需要传递给fn的参数放到一个数组(或者类数组)中传递进去,虽然写的是一个数组,但是也相当于给fn一个个的传递
2.3:bind
bind:语法和call一模一样,区别在于立即执行还是等待执行,bind不兼容IE6~8
3.如何自己实现一个bind方法
bind不会立即执行,而是返回一个改变了上下文this后的函数。 因此我们想要自己实现一个bind函数,就必须返回一个函数,而且这个函数会接收绑定的参数的上下文。
if (!Function.prototype.bind) {
Function.prototype.bind = function () {
if (typeof this != 'function') { // 判断调用者是不是函数
throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
}
var self = this, // 保存原函数 (this指向调用bind者)
context = [].shift.call(arguments), // 把参数中的第一个剪切出来,保存需要绑定的this上下文
args = [].slice.call(arguments); // 剩余的参数转为数组
return function () { // 返回一个新函数
self.apply(context, [].concat.call(args, [].slice.call(arguments)));
}
}
}