JS手动实现call、apply、bind
call
首先先了解call的用法:
let obj1 = {
name: "Tom",
x: 10,
show(y) {
console.log(this.x+y);
}
}
let obj2 = {
name: "Jack",
x:5
}
obj1.show.call(obj2,10);//输出:15
//call(this,a1,a2,a3...)
call第一个参数是改变后的上下文,然后后面的参数就是挨个传进去,但是不是数组的形式。
手动实现的代码
{
//call()的参数:第一个参数就是改变后的上下文,后面可以传若干个参数(不是数组的形式)。
let obj1 = {
name: "Tom",
x: 10,
show(y) {
console.log(this.x+y);
}
}
let obj2 = {
name: "Jack",
x:5
}
obj1.show(10);
Function.prototype.mcall = function (t) {
//首先先进行判断传进来的上下文是不是为空,为空那么就设置上下文为window
if (t == undefined || t == null) {
t = window;
}
t.fn = this;//这里的this就是show函数,同时给t这个对象扩展一个相同的show函数
let arr=[...arguments].slice(1)//去掉第一个参数(因为第一个参数是上下文)
t.fn(...arr)//这里需要把arr用展开运算符打开。
}
obj1.show.mcall(obj2,1,2,3)//输出 为6
}
apply
apply和call的区别就是除了第一个参数是上下文,然后剩下的参数call就是挨个传参数,但是apply就是传一个数组。
具体用法看代码
let obj1 = {
name: "Tom",
x: 1,
show(arr) {
arr.push(this.x)
console.log(arr);
}
}
let obj2 = {
name: "Jack",
x:2
}
obj1.show.apply(obj2,[5,4,3])//输出[5,4,3,2]
然后手动实现apply
{
let obj1 = {
name: "Tom",
x: 1,
show(arr) {
arr.push(this.x)
console.log(arr);
}
}
let obj2 = {
name: "Jack",
x:2
}
Function.prototype.mapply = function (t) {//apply就是接收2个参数,第一个参数就是上下文,第二个就是一个数组。
if (t == undefined || t == null) {
t = window;
}
let arr = [...arguments].slice(1);
t.fn = this;
t.fn(arr)//这里就不需要把数组进行展开,因为apply接收的就是一个数组
}
obj1.show.mapply(obj2,[5,2,3])//输出 [5,2,3,2]
}
bind
bind的区别和call、apply的区别就是修改上下文后,会返回一个新的函数。
然后参数的传递就是和call是一样的。
let obj1 = {
name: "Tom",
x: 10,
show(p) {
console.log(this.x*p);
}
}
let obj2 = {
name: "Jack",
x: 0,
}
let ss=obj1.show.bind(obj2,2)//输出 0
手动实现bind
{
let obj1 = {
name: "Tom",
x: 10,
show(p) {
console.log(this.x*p);
}
}
let obj2 = {
name: "Jack",
x: 0,
}
Function.prototype.mbind = function (t) {
if (t == undefined || t == null) {
t = window;
}
t.fn = this;
let arr = [...arguments].slice(1);
//因为bind修改上下文后会返回一个函数,同时参数不是数组,参数的类型和call类似。
return function () {
t.fn(...arr)
}
}
let ss=obj1.show.mbind(obj2,10)()//输出 0
}