用于 this 的显示绑定(箭头函数不绑定this)
1 call 函数的实现
// 给所有的函数添加一个hycall的方法 原型
Function.prototype.hycall = function(thisArg, ...args) {
// 在这里可以去执行调用的那个函数(foo)
// 问题: 得可以获取到是哪一个函数执行了hycall
// 1.获取需要被执行的函数
var fn = this;
// 2.对thisArg转成对象类型(防止它传入的是非对象类型)
//如果undefined或者null,thisArg=window
thisArg =
thisArg !== null && thisArg !== undefined ? Object(thisArg) : window;
// 3.调用需要被执行的函数
thisArg.fn = fn;
var result = thisArg.fn(...args);
delete thisArg.fn;
// 4.将最终的结果返回出去
return result;
};
2 apply函数的实现
Function.prototype.hyapply = function(thisArg, argArray) {
// 1.获取到要执行的函数
var fn = this;
// 2.处理绑定的thisArg
thisArg =
thisArg !== null && thisArg !== undefined ? Object(thisArg) : window;
// 3.执行函数
thisArg.fn = fn;
var result;
// if (!argArray) { // argArray是没有值(没有传参数)
// result = thisArg.fn()
// } else { // 有传参数
// result = thisArg.fn(...argArray)
// }
// argArray = argArray ? argArray: []
argArray = argArray || [];
result = thisArg.fn(...argArray);
delete thisArg.fn;
// 4.返回结果
return result;
};
3 bind函数的实现
Function.prototype.hybind = function(thisArg, ...argArray) {
// 1.获取到真实需要调用的函数
var fn = this
// 2.绑定this
thisArg = (thisArg !== null && thisArg !== undefined) ? Object(thisArg): window
function proxyFn(...args) {
// 3.将函数放到thisArg中进行调用
thisArg.fn = fn
// 特殊: 对两个传入的参数进行合并
var finalArgs = [...argArray, ...args]
var result = thisArg.fn(...finalArgs)
delete thisArg.fn
// 4.返回结果
return result
}
return proxyFn
}
4 区别对比
- call、apply、bind相同点:都是改变this的指向,传入的第一个参数都是绑定this的指向,在非严格模式中,如果第一个参数是null或者undefined,会把全局对象(浏览器是window)作为this的值,要注意的是,在严格模式中,null 就是 null,undefined 就是 undefined
- call和apply唯一的区别是:call传入的是参数列表,apply传入的是数组,也可以是类数组
- bind和call、apply的区别: bind返回的是一个改变了this指向的函数,便于稍后调用,不像call和apply会立即调用;bind和call很像,传入的也是参数列表,但是可以多次传入,不需要像call,一次传入
- 值得注意:当 bind 返回的函数 使用new作为构造函数时,绑定的 this 值会失效,this指向实例对象,但传入的参数依然生效 (new调用的优先级 > bind调用)