developer-plus / interview

https://interview.developer-plus.org
MIT License
9 stars 1 forks source link

手写题:如何实现call,apply,bind? #3

Open chenfan0 opened 2 years ago

chenfan0 commented 2 years ago

call,apply,bind的区别:

call和apply的区别:

const obj = { name: 'obj' } // call函数在调用时传递给foo的参数要一个一个传递进去。 foo.call(obj, 1, 2) // 1, 2, obj对象 // apply函数在调用时传递给foo的参数要以数组的形式传递进去。 foo.apply(obj, [1, 2]) // 1, 2, obj对象

#### call,apply和bind的区别:
- call和apply函数都会执行原函数,而bind函数不会执行原函数,它会返回一个绑定了this的函数。
```js
function foo(x, y) {
    console.log(x, y)
    console.log(this)
}

const obj = {
    name: 'obj'
}
// bind函数会返回一个新的函数,这个函数的this会被绑定为obj
// 同时传递给原foo函数的参数,可以在bind的时候传递进去,也可以在执行的时候再传递。
// 同样也可以bind的时候传递一部分参数,执行的时候传递剩下的部分参数。
const newFoo = foo.bind(obj, 1)
newFoo(2)  // 1, 2, obj对象

call函数的实现

Function.prototype.myCall = function (thisArgs, ...args) {
    // 获取调用该方法的函数,在上面的例子中,这里的fn就是foo函数
    const fn = this
    // 边界判断,当用户绑定的值为null或者undefined是,将该this赋值为全局的this
    // 当用户希望绑定的this为基本类型的数据,需要使用Object函数将其包装为包装对象
    thisArgs = (thisArgs === undefined || thisArgs === null) ? globalThis : Object(thisArgs)
    // 创建一个symbol作为key,防止属性名冲突。
    const sym = Symbol()
    // 将函数作为属性赋值给thisArgs
    thisArgs[sym] = fn
    // 执行fn函数,并将fn函数的执行结果返回出去
    // 这里函数参数中将thisArgs中的sym属性给删除掉,是为了在函数内打印this对象时,不会有我们添加的sym属性。
    return thisArgs[sym](...(delete thisArgs[sym] === true ? args : []))
}

apply函数的实现

// apply方法和call方法只有第二个参数的不同,在apply方法中这里的args必须为一个数组,所以我们不需要采用剩余参数的写法。
Function.prototype.myApply = function (thisArgs, args) {
    // 如果想要对args参数的类型进行判断,可以自行判断,这里就不对该参数的类型进行判断了。
    // 获取调用该方法的函数,在上面的例子中,这里的fn就是foo函数
    const fn = this
    // 边界判断,当用户绑定的值为null或者undefined是,将该this赋值为全局的this
    // 当用户希望绑定的this为基本类型的数据,需要使用Object函数将其包装为包装对象
    thisArgs = (thisArgs === undefined || thisArgs === null) ? globalThis : Object(thisArgs)
    // 创建一个symbol作为key,防止属性名冲突。
    const sym = Symbol()
    // 将函数作为属性赋值给thisArgs
    thisArgs[sym] = fn
    // 执行fn函数,并将fn函数的执行结果返回出去
    // 这里函数参数中将thisArgs中的sym属性给删除掉,是为了在函数内打印this对象时,不会有我们添加的sym属性。
    return thisArgs[sym](...(delete thisArgs[sym] === true ? args : []))
}

bind函数的实现

Function.prototype.myBind = function (thisArgs, ...args) {
     // 获取调用该方法的函数,在上面的例子中,这里的fn就是foo函数
    const fn = this
    // 边界判断,当用户绑定的值为null或者undefined是,将该this赋值为全局的this
    // 当用户希望绑定的this为基本类型的数据,需要使用Object函数将其包装为包装对象
    thisArgs = (thisArgs === undefined || thisArgs === null) ? globalThis : Object(thisArgs)
    // 创建一个symbol作为key,防止属性名冲突。
    const sym = Symbol()
    // 返回一个函数
    return function(...args1) {
        // 将第一次传递的参数和第二次传递的参数合并起来
        const totalArgs = [...args, ...args1]
        thisArgs[sym] = fn

        return thisArgs[sym](...(delete thisArgs[sym] ? totalArgs : []))
    }
}