this指向
this本质是一个变量,指向保存在堆中的某个对象的数据
this的指向遵循四个规则,由高到低分别是以下四点
1、new 关键字创建的对象
function Person(name){
this.name = name;
}
const person = new Person('zs')
console.log(person.name) // zs
this 指向创建的对象
2、用call/apply/bind改变this(显式绑定)
this指向新绑定
3、函数作为对象方法调用(隐式绑定)
this指向该对象
4、其他
this 严格模式为underfined,非严格模式为window
call源码解析
Function.prototype.myCall = function (context, ...args) {
//这里的this是person,参考上面的3
if (typeof this !== 'function') {
throw new TypeError('Function.prototype.call - what is trying to be called is not callable');
}
const fn = Symbol('fn'); // 创建一个唯一的 Symbol
context = context || window; // 如果没有传递 context,则默认为全局对象 window
context[fn] = this; // 将当前函数作为 context 对象的一个属性
const result = context[fn](...args); // 调用函数,并传递参数列表
delete context[fn]; // 删除添加的属性
return result; // 返回函数执行结果
};
function person(a,b,c){
let name = "ls"
console.log(this.name,a,b,c)
return "ok"
}
let zs={name:"zs"}
person.myCall(zs,"test1","test2","test3") //zs test1 test2 test3
改变person的this,this从指向windox改为对象zs
核心是将person变为zs的函数,利用zs取调用,this就变成了zs
apply源码解析
call和apply的区别,call是接收一系列的参数,apply是接收一个数组
Function.prototype.myApply = function (context, args) {
if (typeof this !== 'function') {
throw new TypeError('Function.prototype.apply - what is trying to be called is not callable');
}
const fn = Symbol('fn'); // 创建一个唯一的 Symbol
context = context || window; // 如果没有传递 context,则默认为全局对象 window
context[fn] = this; // 将当前函数作为 context 对象的一个属性
let result;
if (args && args.length) {
result = context[fn](...args); // 如果传递了参数列表,则使用扩展运算符将参数列表展开
} else {
result = context[fn](); // 如果没有传递参数列表,则直接调用函数
}
delete context[fn]; // 删除添加的属性
return result; // 返回函数执行结果
};
function person(...args){
let name = "ls"
console.log(this.name,...args)
return "ok"
}
let zs={name:"zs"}
person.myApply(zs,["test1","test2","test3"]) //zs test1 test2 test3
bind源码解析
Function.prototype.myBind = function (context, ...args) {
if (typeof this !== 'function') {
throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
}
const fn = this; // 当前this为person,是person调用的myBind
return function(){ //返回一个函数
return fn.apply(context,args) //改变this指向,并取返回值
}
};
function person(a,b,c){
let name = "ls"
console.log(this.name,a,b,c)
return "ok"
}
let zs={name:"zs"}
const result = person.myBind(zs,1,2,3)
result() //zs 1 2 3
console.log(result()) // zs 1 2 3 ok
bind接收的是一系列参数
bind返回是一个函数,需要手动调用