改变this的指向:Function.prototype: call/apply/bind
call/apply
-
都是立即执行函数,并且改变函数中的this和传递参数。
-
区别: 传递参数的区别,apply需要将传递的参数放到一个数组,而call是一个个传递,结果都是把这些参数一个个的传递给fn;
call: 在非严格模式下,context不传或者传递null/undefined,则this都改为window,严格模式下,不传是undefined,否则传递谁,就是谁。
重写call
/*
* 重写内置的call: 把需要执行的函数和需要改变的this关联在一起
* +context.xxx = this;
* + context.xxx() 类似于obj.fn()
*/
Function.prototype.call = function call(context, ...parmas) {
context = context == null ? window : context;
context = !/^(function|object)$/.test(typeof context) ? Object(context): context;
let self = this,
result = null,
key = Symbol('key'); //新增的属性名保证唯一性,放置污染对象原有的成员
context[key] = self;
result = context[key](...params);
delete context[key]; //用完后移除新增的成员
return result;
}
重写bind
/*
* 重写bind : 柯里化思想 【参数预处理】
*/
Function.prototype.bind = function bind(context, ...outaArgs) {
let self = this;
return function(...innerArgs) {
self.call(context, ...outerArgs.concat(innerArgs))
}
}