call、apply 和 bind 是挂在 Function 对象上的三个方法,调用这三个方法的必须是一个函数。
在浏览器里,在全局范围内this 指向window对象;
在函数中,this永远指向最后调用他的那个对象;
构造函数中,this指向new出来的那个新的对象;
call、apply、bind中的this被强绑定在指定的那个对象上;
箭头函数中this比较特殊,箭头函数this为父作用域的this,不是调用时的this.要知道前四种方式,都是调用时确定,也就是动态的,而箭头函数的this指向是静态的,声明的时候就确定了下来;
apply、call、bind都是js给函数内置的一些API,调用他们可以为函数指定this的执行,同时也可以传参。
三者大同小异,先来以call为例解析一下过程
var foo = { value: 1}
// 如果不对this进行绑定执行bar() 会返回undefined
function bar () { console.log(this.value)}
bar.call(foo) // 1 也就是说call()改变了this的指向,指向了foo
试想当调用call的时候,也就是类似于
var foo = {
value: 1,
bar: function(){ console.log(this.value) }
}
foo.bar() //1
也就是说步骤可以是这样
1、将函数设为对象的属性
2、执行这个函数
3、删除这个函数
下面就试着去实现一下(CALL):
Function.prototype.call2 = function (context) {
context.fn = this //this 也就是调用call的函数,将函数设为对象的属性
var result = context.fn() // 执行这个函数
delete context.fn // 删除这个函数
return result
}
var foo = { value: 1}
function bar () { console.log(this.value)}
bar.call2(foo) // 1
apply
Function.prototype.apply2 = function(context) {
var context = context || window
context.fn = this
var args = arguments[1]
var result = context.fn(...args)
delete context.fn
return result
}
bind
Function.prototype.bind2 = function(context) {
var self = this
var [, ...args] = arguments;
return function () {
return self.apply2(context, args) // 或者 //return self.apply(context, args)
}
}