call&apply&bind
1、call, apply 都属于Function.prototype的方法,因为属于Function.prototype,所以每个Function对象实例,也就是每个方法都有call, apply属性。call、apply它们的作用都是一样的都是也是改变执行上下文的对象,只是使用方式不同而已。
2、bind 也是改变执行上下文的对象。
在Javascript中,代码总有一个执行上下文对象,那么当我手动改变它时,就可以改变这个执行上下文,也就可以将非自己的方法成为自己的方法。
3、call或apply是将执行上下文对象换了后,立即执行;而bind是将执行上下文对象换了后,创建一个新函数。
方法执行上下文this 指向问题
最精简的解释:this 指向调用函数时用的引用
JS 规定,当存在一个对象调用函数时,那么该函数的 this 指向的就是该对象 如果一个函数不存在对象调用它,那么该函数的 this 指向的就是全局的 window
call、 apply、bind用法
call
fn.call(obj, arg1, arg2, arg3)
定义:应用某一个对象的一个方法,用另一个对象替换当前对象。
apply
fn.apply(thisObj, [arg1, arg2, arg3])
定义:应用某一个对象的一个方法,用另一个对象替换当前对象。
说明:如果参数不是数组类型的,则会报一个TypeError错误。
apply与call的唯一区别就是接收参数的格式不同。
var name = 'windowName';
//方法a的作用,是输出对象的名字
function a(x, y) {
console.log(this.name)
console.log(x + y)
}
function b(){
this.name = 'bName';
}
a(2, 8) // windowName 10
a.call(new b(), 2, 8) // bName 10
a.apply(new b(), [2, 8]) //bName 10
bind
fn.bind(thisObj, arg1, arg2, arg3) bind方法创建一个新的函数,在bind()被调用时,这个新函数的this被bind的第一个参数指定,其余的参数将作为新函数的参数供调用时使用。
var name = 'windowName';
//方法a的作用,是输出对象的名字
function a(x, y) {
console.log(this.name)
console.log(x + y)
}
function b(){
this.name = 'bName';
}
a(2, 8) // windowName 10
var c = a.bind(new b(), 2)
c(8) //bName 10
call 实现
Function.prototype.myCall = function(context, ...args) {
// 判断是否是undefined和null
if (typeof context === 'undefined' || context === null) {
context = window
}
let fnSymbol = Symbol()
context[fnSymbol] = this
let fn = context[fnSymbol] (...args)
delete context[fnSymbol]
return fn
}
apply 实现
Function.prototype.myApply = function(context, args) {
// 判断是否是undefined和null
if (typeof context === 'undefined' || context === null) {
context = window
}
let fnSymbol = Symbol()
context[fnSymbol] = this
let fn = context[fnSymbol] (...args)
return fn
}
bind 实现
Function.prototype.myBind = function(context) {
// 判断是否是undefined和null
if (typeof context === "undefined" || context === null) {
context = window;
}
self = this;
return function(...args) {
return self.apply(context, args);
}
}