手写实现call apply bind
2021-12-22 本文已影响0人
贵贵贵子
call apply bind 区别
这三个都是Function中自带的三个方法,都是可以改变this指向的,在Function.prototype上 可以打印看一下
console.dir(Function.prototype); //你会看的这三个属性以及arguments,toString等属性
call,apply的特点
- 如果传入的是值类型 this指向对应类型的构造函数创建的实例
- 如果传入的是对象 this指向对象本身
- 如果传入 undefined 或者 null this为空对象
call apply bind 用法
let name = "张三";
let Person = {
name: "法外狂徒",
age: 18,
};
function say(lag) {
console.log(this);
console.log(`my name is ${this.name},my age is ${this.age},我说${lag}`);
}
say("I love you"); //此时会打印Window my name is 张三,my age is undefined,我说I love you;此时this指的是window可以获取到全局变量name
//call
say.call(Person , "I love you"); //my name is 法外狂徒,my age is 18,我说I love you, 此时函数中this就指向了Person
//apply
say.apply(Person, ["I love you"]); //my name is 法外狂徒,my age is 18,我说I love you 和call除了参数传数组外没什么不同
//bind
say.bind(Person, "I love you")(); //my name is 法外狂徒,my age is 18,我说I love you;bind返回的是一个函数,需要执行
实现call
在Function原型上加上自己的方法myCall;具体细节在注释
Function.prototype.myCall = function (ctx, args) {
ctx = ctx ? Object(ctx) : window;
args = args || [];
const key = Symbol(); //创建一个独一无二的key以免覆盖原有属性
ctx[key] = this; //将this赋值到传入对象ctx的某一个属性上;this指的是函数,结合上下文这里this就是say函数
const result = ctx[key](...args); //将入参解构传入;并用result接收返回值
delete ctx[key]; //用完后将此属性删除;不然每次call这个对象都会加个属性
return result; //返回函数返回值
};
//执行myCall
say.myCall(Person, ["I love you"]); //my name is 法外狂徒,my age is 18,我说I love you
实现apply
apply和call只是传参区别,稍微修改下即可;直接复制过来
Function.prototype.myApply = function (ctx, ...args) {
ctx = ctx ? Object(ctx) : window;
args = args || [];
const key = Symbol(); //创建一个独一无二的key以免覆盖原有属性
ctx[key] = this; //将this赋值到传入对象ctx的某一个属性上;this指的是函数,结合上下文这里this就是say函数
const result = ctx[key](...args); //将入参解构传入;并用result接收返回值
delete ctx[key]; //用完后将此属性删除;不然没吃call这个对象都会加个属性
return result; //返回函数返回值
};
//执行myApply
say.myApply(Person, "I love you"); //my name is 法外狂徒,my age is 18,我说I love you
实现bind
bind 是返回一个函数
Function.prototype.myBind = function (ctx, ...args) {
ctx = ctx ? Object(ctx) : window;
args = args || [];
const _this =this
return function (...rest) {
const key = Symbol(); //创建一个独一无二的key以免覆盖原有属性
console.log(this)//这里的this指向window,因为返回的是一个函数,this永远指向最后调用它的那个对象,最终调用这个函数的是window
ctx[key] = _this; //将this赋值到传入对象ctx的某一个属性上;this指的是函数,结合上下文这里this就是say函数
const result = ctx[key](...args,...rest); //将入参解构传入;并用result接收返回值
delete ctx[key]; //用完后将此属性删除;不然没吃call这个对象都会加个属性
return result; //返回函数返回值
};
};
//执行myBind
say.myBind(Person, "I love you 1")(); //my name is 法外狂徒,my age is 18,我说I love you