Skip to content

call,apply和bind的区别及实现原理 #79

Open
@TieMuZhen

Description

@TieMuZhen

call、apply、bind的区别

callapply的功能相同,区别在于传参的方式不一样:

  • fn.call(obj, arg1, arg2, ...),调用一个函数, 具有一个指定的this值和分别地提供的参数(参数的列表)。
  • fn.apply(obj, [argsArray]),调用一个函数,具有一个指定的this值,以及作为一个数组(或类数组对象)提供的参数。
  • fn.bind(obj, arg1, arg2, ...),bind 方法的返回值是函数,并且需要稍后调用,才会执行。而 apply 和 call 则是立即调用。

call的源码实现

  • 如果不传入参数或者参数为null,默认指向为 window / global
  • 指定this指向到参数上的函数
  • 使用给定的参数来执行函数
  • 删除参数上的函数
Function.prototype.call = function () {
    let [obj, ...args] = [...arguments];
    // 如果第一个参数传入的是 null 或者是 undefined, 那么指向this指向 window/global
    if (obj === null) {
        obj = typeof window === 'undefined'? global: window;
        // obj = globalThis;
    }
    obj.func = this; // 添加新属性,新属性赋值为this(即调用`.call`的函数)
    const result = obj.func(...args);
    delete obj.func; // 删除多添加的属性
    return result;
}

测试代码

var foo = {
    name: 'Selina'
}
var name = 'Chirs';
function bar(job, age) {
    console.log(this.name, job, age);
}
bar.call(foo, 'programmer', 20);
// Selina programmer 20
bar.call(null, 'teacher', 25);
// 浏览器环境: Chirs teacher 25; node 环境: undefined teacher 25

apply的源码实现

Function.prototype.apply = function () {
    let [obj, ...args] = [...arguments];
    // 如果第一个参数传入的是 null 或者是 undefined, 那么指向this指向 window/global
    if (obj === null) {
        obj = typeof window === 'undefined'? global: window;
        // obj = globalThis;
    }
    obj.func = this; // 添加新属性,新属性赋值为this(即调用`.call`的函数)
    // 因为apply传的第二个参数是数组,
    // 使用解构赋值获得的args会被多包一层括号
    // 使用args[0]去掉最外层多包的一层括号
    const result = obj.func(...args[0]); 
    delete obj.func; // 删除多添加的属性
    return result;
}

测试代码

var foo = {
    name: 'Selina'
}
var name = 'Chirs';
function bar(job, age) {
    console.log(this.name, job, age);
}
bar.apply(foo, ['programmer', 20]);
// Selina programmer 20
bar.apply(null, ['teacher', 25]);
// 浏览器环境: Chirs programmer 20; node 环境: undefined teacher 25

bind的源码实现

Function.prototype.bind = function () {
    let [obj, ...args] = [...arguments];
    // 如果第一个参数传入的是 null 或者是 undefined, 那么指向this指向 window/global
    if (!obj) {
        obj = typeof window === 'undefined'? global: window;
    }
    const that = this;
    return function() {
        return that.apply(obj, [...args, ...arguments]);
    }
}

测试代码

var name = 'Jack';
function person(age, job, gender){
    console.log(this.name, age, job, gender);
}
var Yve = {name : 'Yvette'};
let result = person.bind(Yve, 22, 'enginner')('female');
// Yvette 22 enginner female

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions