this绑定方式(共4种方式):默认绑定、隐式绑定、硬绑定(call,apply,bind)、new绑定
this的五种情况分析
this执行主体,谁把它执行的「和在哪创建&在哪执行都没有必然的关系」
函数执行,看方法前面是否有“点”,没有“点”,this是window「严格模式下是undefined」,有“点”,“点”前面是谁this就是谁
给当前元素的某个事件行为绑定方法,当事件行为触发,方法中的this是当前元素本身「排除attachEvent」
构造函数体中的this是当前类的实例
箭头函数中没有执行主体,所用到的this都是其所处上下文中的this
可以基于Function.prototype上的call/apply/bind去改变this指向
手撕call/bind/apply源码
手撕call 原理:就是利用 “点”定this机制,context.xxx=self “obj.xxx=function ” => obj.xxx()
Function.prototype._call = function (context, ...params) {
if (typeof context === "function") {
throw new TypeError('参数类型错误');
return;
}
let key = Symbol('fun');
context = context || window;
context[key] = this;
context[key](...params);
delete context[key];
};
手撕bind (把function执行并且改变this即可 args->是执行proxy的时候可能传递的值)
Function.prototype._bind = function (context, ...params) {
if (typeof context === "function") {
throw new TypeError('参数类型错误');
return;
}
let self = this;
context = context || window;
return function (...arg) {
let key = Symbol('fun');
context[key] = self;
context[key](...[...params, ...arg]);
delete context[key];
};
};
手撕apply
Function.prototype._apply = function (context, params) {
if (typeof context === "function") {
throw new TypeError('参数类型错误');
return;
}
let key = Symbol('fun');
context = context || window;
context[key] = this;
context[key](...params);
delete context[key];
};