call
- Function.prototype.call
- call() 方法接受的是一个参数列表
基本使用
function Product(name, price) {
this.name = name;
this.price = price;
}
function Food(name, price) {
Product.call(this, name, price);
this.category = "food";
}
console.log(new Food("cheese", 5).name);
// Expected output: "cheese"
手撕
- call 是将函数作为属性挂载到当前传入的执行上下文这样达到绑定效果
- 然后执行 context.fn(...args)
- 删除 context.fn,将结果返回
注意如果函数的最后一个命名参数以 ... 为前缀,则它会将所有后面剩余的是实参个数包裹成一个数组。
// 例子
function test(a, b, ...args) {
console.log(args);
}
test(1, 2, 3, 4); // [3, 4]
context 是函数执行上下文,args 是传入的多个参数的数组
Function.prototype.myCall = function (context, ...args) {
context = context || window;
args = args || [];
//唯一性,当前this就要执行的函数
const fn = Symbol();
context[fn] = this;
//执行函数,保留结果...args把数组展开为一项一项
let res = context[fn](...args);
delete context[fn];
return res;
};
test
Function.prototype.myCall = function (context, ...args) {
context = context || window;
args = args || [];
//唯一性,当前this就要执行的函数
const fn = Symbol();
context[fn] = this;
//执行函数,保留结果
let res = context[fn](...args);
delete context[fn];
return res;
};
age = 18;
let obj = {
age: 10,
};
function say() {
console.log(this.age);
}
say(); //18
say.myCall(obj); //10
apply
- Function.prototypr.apply
- apply() 方法接受的是一个参数数组
基本使用
const numbers = [5, 6, 2, 3, 7];
const max = Math.max(numbers); //NaN
console.log(max); //给定数值中最大的数。如果任一参数不能转换为数值,则返回 NaN。如果没有提供参数,返回 -Infinity。
const min = Math.min.apply(null, numbers);
console.log(min);
// Expected output: 2
Function.prototype.myApply=function(context.args){
context=conetxt||window
args=args||[]
let fn=Symbol()
context[fn]=this
let res=context[fn](...args)
delete context[fn]
return res
}
test
const numbers = [5, 6, 2, 3, 7];
Function.prototype.myApply = function (context, args) {
context = context || window;
args = args || [];
let fn = Symbol();
context[fn] = this;
let res = context[fn](...args);
delete context[fn];
return res;
};
console.log(Math.max.myApply(null, numbers)); //7
bind
- bind 是返回函数
基本使用
const module = {
x: 42,
getX: function () {
return this.x;
},
};
const unboundGetX = module.getX;
console.log(unboundGetX()); // The function gets invoked at the global scope
// Expected output: undefined
const boundGetX = unboundGetX.bind(module);
console.log(boundGetX());
// Expected output: 42
可以二次传值
const mbs = {
name: "麻不烧",
say(prefix, age) {
console.log(`${prefix},my name is ${this.name},i am ${age} year old`);
},
};
mbs.say("hello", 12); // 'hello,my name is 麻不烧,i am 12 year old'
const B = {
name: "小丁丁",
};
const sayB = mbs.say.bind(B, "hello");
sayB(3); // 'hello,my name is 小丁丁,i am 3 year old''
手撕
明确是要返回一个函数
Function.prototype.myBind = function (context, ...outArgs) {
context = context || window;
outArgs = outArgs || [];
let fn = Symbol();
context[fn] = this;
return function (...innerArgs) {
//第二次传递参数
return context[fn](...outArgs, ...innerArgs);
delete context[fn];
};
};
test
const mbs = {
name: "麻不烧",
say(prefix, age) {
console.log(`${prefix},my name is ${this.name},i am ${age} year old`);
},
};
mbs.say("hello", 12); // 'hello,my name is 麻不烧,i am 12 year old'
const B = {
name: "小丁丁",
};
const sayB = mbs.say.bind(B, "hello");
Function.prototype.myBind = function (context, ...outArgs) {
context = context || window;
outArgs = outArgs || [];
let fn = Symbol();
context[fn] = this;
return function (...innerArgs) {
//第二次传递参数
return context[fn](...outArgs, ...innerArgs);
};
};
console.log(mbs.say.myBind(B, "hello", 18)());
本质就是一个对象挂载一个属性,而属性就是一个函数。
参考 链接:juejin.cn/post/712823…