手写call、apply和bind

简介: 手写call、apply和bind

手写call

原生call具备的三个功能

  1. 改变this指向。
  2. 调用call就是调用函数。(能够返回结果)

实现代码

function person(a,b,c) {
    return {
        name: this.name,
        a: a,
        b: b,
        c: c
    }
}
const egg = {name: 'hello'};
Function.prototype.myCall = function(obj) {
    obj = obj || window
    obj.p = this;
    const newArg = [];
    for (let i = 1; i < arguments.length; i++) {
        newArg.push(arguments[i]);
    }
    const result = obj.p(...newArg);
    delete obj.p;
    return result;
}
person.myCall(egg,'点赞','收藏','转发')
person.call(egg,'点赞','收藏','转发')
复制代码

2. 手写apply

apply和call很类似,区别在于apply只接受两个参数,一个是this的指向,另一个是是一个数组。

原生apply具备的几个功能

  1. 改变this指向。
  2. 调用函数并接受返回值。

实现代码

function person(a,b,c) {
    return {
        name: this.name,
        a: a,
        b: b,
        c: c
    }
}
const egg = {name: 'hello'};
Function.prototype.myApply = function(obj,arr) {
    obj.p = this;
    let result;
    if (!arr) {
        result = obj.p();
    } else {
        result = obj.p(...arr);
    }
    delete obj.p;
    return result;
}
person.myApply(egg,['点赞','收藏','转发'])
person.apply(egg,['点赞','收藏','转发'])
复制代码

3. 手写bind

原生bind具备的功能

  1. 会返回一个函数。(这个返回的函数应该是改变过this的,并且接受参数就能执行的)
  2. 会修改this指向。
  3. 原生bind方法返回的函数如果通过new创建实例的时候,会使得this失效。不调用new,this不会失效。

注意事项

  1. arguments其实是对象,而不是数组。
  2. 使用Array.prototype.slice.call(arguments,1):可以获取arguments包括第二个元素之后的所有元素,并将其装换为数组。
  3. 下面的题解涉及到了原型链的知识,值得我们多次反复揣摩。

实现代码

function person(a,b,c) {
    console.log(this.name);
    console.log(a,b,c);
}
const egg = {name: 'hello'};
Function.prototype.myBind = function(obj) {
    let that = this;
    let arr = Array.prototype.slice.call(arguments,1);
    // 定义一个空函数作为桥梁
    let empty = function() {}
    let newf = function () {
        let arr2 = [].slice.call(arguments);
        let arrSum = arr.concat(arr2);
        // 判断是否调用了new
        if (this instanceof empty) {
            that.apply(this,arrSum);
        } else {
            that.apply(obj,arrSum);
        }
    }
    empty.prototype = that.prototype;
    newf.prototype = new empty;
    return newf;
}
const bibi = person.myBind(egg,'点赞','投币')
// const b = new bibi('充电')
bibi('充电')
// person.apply(egg,['点赞','收藏','转发'])
复制代码

参考链接

原生JavaScript实现call、apply和bind - Web前端工程师面试题讲解

启示

  • 首先call、apply、bind看似简单,实则需要很强的基本功。
  • 本文需要多次反复阅读,揣摩,加油,希望多看几遍!
相关文章
|
1月前
|
JavaScript 前端开发 开发者
call、bind、apply区别
【10月更文挑战第26天】`call`、`bind` 和 `apply` 方法在改变函数 `this` 指向和参数传递方面各有特点,开发者可以根据具体的需求和使用场景选择合适的方法来实现更灵活和高效的JavaScript编程。
30 1
|
2月前
|
前端开发 JavaScript
比较一下apply/call/bind ?
本文首发于微信公众号“前端徐徐”,详细介绍了 JavaScript 中 `apply`、`call` 和 `bind` 方法的概念、使用场景及手动实现。主要内容包括: - **apply**:使用数组作为参数调用函数,并指定 `this`。 - **call**:直接传递参数调用函数,并指定 `this`。 - **bind**:返回一个绑定了 `this` 和部分参数的新函数。 文章还对比了这三个方法的区别,并提供了手动实现的代码示例。
23 2
|
4月前
|
JavaScript 前端开发 测试技术
手写call , apply , bind 方法的实现
本文通过实例讲解了JavaScript中`call`、`apply`及`bind`方法的用途与实现。以`call`为例,展示了如何改变函数内的`this`指向,并立即执行该函数。通过在`Function.prototype`上定义`myCall`,利用`Symbol`确保新增属性的唯一性,从而避免命名冲突。接着介绍了如何处理不定数量的参数传递,最终实现了自定义的`myCall`方法。随后简述了`apply`与`call`的区别,并展示了其实现方式,主要在于参数传递形式的不同。最后,通过`bind`方法创建了一个返回新函数的例子,该新函数具有固定的`this`上下文,同时支持分批参数传递。
38 2
手写call , apply , bind 方法的实现
|
5月前
|
JavaScript
js【详解】bind()、call()、apply()( 含手写 bind,手写 call,手写 apply )
js【详解】bind()、call()、apply()( 含手写 bind,手写 call,手写 apply )
29 0
|
JavaScript 前端开发
面试官: call、apply和 bind有什么区别?
面试官: call、apply和 bind有什么区别?
|
7月前
call\apply\bind详解
call\apply\bind详解
37 0
bind、call、apply 区别
bind、call、apply 区别
82 0
手写call-apply-bind以及了解柯里化
手写call-apply-bind以及了解柯里化
call、apply、bind笔记
call、apply、bind笔记
65 0

热门文章

最新文章