抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

一:手写call方法

1. call()方法

call方法是用于调用函数的方法,并且可以接收参数

1
function.call(thisArg, arg1, arg2, ...)
  • function:要调用的函数
  • thisArg:可选参数,指定函数执行时的上下文,即内部函数的this的值。如果不传,this的值将为全局对象
  • agr1, arg2…:可选参数,要传递给函数的参数列表

使用call()方法可以方便地修改函数的执行上下文,使其在不同的对象上执行,以达到灵活性和重用性的目的。

2. es6实现call方法

  • 需要满足call方法的几个条件
    • 所有函数都可以调用myCall方法
    • 调用原函数并且将this绑定到指定的对象
    • 接收不定量的参数,并且返回结果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//实现代码
Function.prototype.myCall = function (thisArg, ...args)
{
//如果为提供 thisArg绑定到window上
thisArg = thisArg || window
//使用symbol
const key = Symbol('key')
//thisArg.f是fn函数的引用
thisArg[key] = this
//调用该函数
const res = thisArg[key](...args)
//删除对象上的f函数
delete thisArg[key]
//此时fn的this就指向obj
return res
}

function fn (numberA, numberB, numberC)
{
return numberA + numberB + numberC
}

let res = fn.myCall(obj, 2, 4, 6)

image-20230912211930591

  • 通过给函数原型上添加myCall方法实现所有函数能够调用该方法

  • 要改变This的指向,就需要获取原函数的引用和传入的对象

  • fn.myCall(obj, 2, 4, 6),我们在调用函数的时候,就隐式绑定了myCall方法的this值为fn函数,所以this的值就是fn函数的引用

  • 通过将该函数的引用添加到需要绑定的对象的属性上,即给thisArg添加原函数的引用,并执行,形如obj.fn(),隐式绑定将fn函数的this值绑定到obj对象上

    • 但由于设定变量来保存原函数的引用,可能会导致设置的变量与原有的对象中的属性命名冲突,缩小了命名空间
    • 利用es6方法中的symbol()构造函数,每次调用返回一个独一无二的值,利用该特性来实现设置的变量不会与原有属性冲突
  • 利用…args剩余参数语法,动态接收不定量的参数,并将它们作为数组存储在args中

  • 最后利用delete关键字再删除绑定对象中的该属性

二:手写apply方法

1. apply()方法

apply()方法是调用原函数的同时可以指定原函数this的值,并传递一个参数数组

1
function.apply(thisArg, [argsArray])
  • function: 原函数
  • thisArg:可选参数,指定函数执行时的上下文,即内部函数的this的值。如果不传,this的值将为全局对象
  • [argsArrray]:一个数组或类数组对象,包含了要传递给函数的参数。

2. es6实现apply方法

  • apply方法与call方法区别就是接收参数的形式不同
    • call方法接收参数是不定参数,接收时候就需要用到es6的剩余参数
    • apply方法传递的是一个参数数组,只需要在调用原函数的时候,利用展开运算符将数组展开传递参数即可
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Function.prototype.myApply = function (thisArg, args)
{
//如果未传obj,this绑定到window对象上
thisArg = thisArg || window
//绑定this并调用原函数
const key = Symbol('key')
thisArg[key] = this
//接收返回值
const res = thisArg[key](...args)
//删除该属性
delete thisArg[key]
//返回结果
return res
}

//测试
const obj = {
name: 'xxx'
}

function fn (numberA, numberB)
{
return numberA + numberB
}

let res = fn.myApply(obj, [2, 4])
console.log('结果:' + res);

三:手写bind方法

1. bind()方法

bind方法用于创建一个新函数,并给指定对象绑定原函数的this的值,并在调用的时候传递给Bind()方法的参数作为新函数的预置参数

1
function.bind(thisArg[, arg1[, arg2[, ...]]])
  • thisArg:在新函数中被绑定为 this 值的对象。
  • arg1, arg2, ...:作为新函数的预置参数,可选。

2. es6实现bind方法

  • 创建一个新函数,即返回一个函数
  • 利用call或apply方法绑定this的值
  • 通过展开运算符 ...args1bind() 方法的第二个及后续参数)和 args2(新函数的参数)合并为一个数组,然后传递给 apply() 方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Function.prototype.myBind = function (thisArg, ...args1)
{
//返回一个函数
return (...args2) =>
{
//绑定this
//拿到fn函数 -- 箭头函数的This捕获上一级作用域的this值,即myBind函数的This,是fn函数
return this.call(thisArg, ...args1, ...args2)
}
}

//测试
const obj = {
name: 'xxx'
}

function fn (numberA, numberB, numberC, numberD)
{
return numberA + numberB + numberC + numberD
}
//绑定但是不调用
let tempFn = fn.myBind(obj, 2, 4)
let res = tempFn(6, 8)
console.log('结果:' + res);

image-20230912220956039

评论