call實(shí)現(xiàn)原理:
~ function () {
/* 內(nèi)置CALL實(shí)現(xiàn)原理 */
function call(context, ...params) {
// this->要執(zhí)行的函數(shù)func context->要改變的函數(shù)中的this指向obj
// params->未來(lái)要傳遞給函數(shù)func的實(shí)參信息{數(shù)組} [100,200]
// 臨時(shí)設(shè)置的屬性灾梦,不能和原始對(duì)象沖突挖函,所以我們屬性采用唯一值處理
context == null ? context = window : null;
if (!/^(object|function)$/.test(typeof context)) context = Object(context);
let self = this,
key = Symbol('KEY'),
result;
context[key] = self;
result = context[key](...params);
delete context[key];
return result;
};
Function.prototype.change = change;
}();
let obj = {
name: 'Alibaba',
xxx: 100,
[Symbol('KEY')]: 200
};
function func(x, y) {
this.total = x + y;
return this;
}
let res = func.call(obj, 100, 200);
console.log(res); //res => {name:'Alibaba',total:300} */
bind實(shí)現(xiàn)原理:
~ function () {
function bind(context, ...params) {
// this->func context->obj params->[100,200]
let self = this;
return function proxy(...args) {
// args->事件觸發(fā)傳遞的信息镶苞,例如:[ev]
params = params.concat(args);
return self.call(context, ...params);
};
};
Function.prototype.bind = bind;
}();
function func() {
console.log(this, arguments);
}
var obj = {
name: 'Alibaba'
};
document.body.onclick = func.bind(obj, 100, 200);
bind的原理袍祖,其實(shí)就是利用閉包的機(jī)制怖辆,把要執(zhí)行的函數(shù)外面包裹一層函數(shù)
document.body.onclick = function proxy(ev) {
// 最后的目的:把func執(zhí)行,this改為obj裕菠,參數(shù)100/200/ev傳遞給他即可
func.call(obj, 100, 200, ev);
};
bind & call/apply:
都是為了改變函數(shù)中的this指向
- call/apply:立即把函數(shù)執(zhí)行
- bind:不是立即把函數(shù)執(zhí)行,只是預(yù)先把THIS和后期需要傳遞的參數(shù)存儲(chǔ)起來(lái)「預(yù)處理思想 -> 柯理化函數(shù)」
- bind的多次綁定只有第一次是有效的