巩固下js中Call、Apply和Bind的区别

call、apply和bind方法是自己经常会 见到而且很容易搞混的方法。前段时间突然看到一篇相关文章。特意自己总结下,加深记忆。

前段时间刷掘金,看到一片文章:《js基础-面试官想知道你有多理解call,apply,bind》

发现自己经常记混淆这几种方法的用法,读完文章后自己做个简单的总结

call、apply、bind都是函数原型上的方法,所以只有函数才能调用他们,否则会出错

1
2
3
4
5
6
7
8
const fun = function () {
return 1;
};
const str = '';
const obj = {};
console.log('fun.call=', fun.call(null)); // 输出: 1
console.log('str.call=', str.call(null)); // Uncaught TypeError: str.call is not a function
console.log('obj.call=', obj.call(null)); // Uncaught TypeError: str.call is not a function

作用:

改变函数运行时的this指向

用法:

1
2
3
fun.call(thisObj, params1, params2, params2, ...)
fun.apply(thisObj, [params1, params2, params2, ...])
fun.bind(thisObj, params1, params2, params2, ...)

call/apply与bind的区别

参数:

==thisObj==:

  1. fun的this要指向的地方
  2. 非严格模式下:thisArg为空或者指定为null,undefined,fun中的this指向window对象.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    const fun = function () {
    console.log(this); // 输出的this都是 window
    };

    console.log('call ===>')
    fun.call(undefined) // fun.call() fun.call(null)
    console.log('apply ===>')
    fun.apply(undefined) // fun.apply() fun.apply(null)
    console.log('bind ===>')
    fun.bind(undefined)() // fun.bind() fun.bind(null)
  3. 严格模式下:thisArg为空或者指定为undefined时fun的this为undefined;当thisArg为null时,输出null
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12

    const fun = function () {
    "use strict";
    console.log(this); // undefined or null
    };

    console.log('call ===>')
    fun.call(undefined) // fun.call() fun.call(null)
    console.log('apply ===>')
    fun.apply(undefined) // fun.apply() fun.apply(null)
    console.log('bind ===>')
    fun.bind(undefined)() // fun.bind() fun.bind(null)
  4. 值为原始值(数字,字符串,布尔值)的this会指向该原始值的自动包装对象,如 String、Number、Boolean
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const fun = function () {
console.log(this);

};

console.log('call ===>');
fun.call(12); // =>this输出为: Number {12}
fun.call('abc'); // =>this输出为: String {"abc"}
fun.call(false); // =>this输出为: Boolean {false}
console.log('apply ===>');
fun.apply(12);// =>this输出为: Number {12}
fun.apply('abc');// =>this输出为: String {"abc"}
fun.apply(false);// =>this输出为: Boolean {false}
console.log('bind ===>');
fun.bind(12)();// =>this输出为: Number {12}
fun.bind('abc')();// =>this输出为:String {"abc"}
fun.bind(false)();// =>this输出为: Boolean {false}

==params==:

  1. 非必需。传给fun的参数
  2. apply接收的是一个数组,call/bind是单个参数传入
执行:

call/apply改变了函数的this上下文后,马上执行该函数

bind则是返回改变了上下文后的函数,不执行该函数

返回值:

call/apply 返回fun的执行结果

bind返回fun的拷贝,并指定了fun的this指向,保存了fun的参数。

使用:
  1. 参数数量/顺序确定就用call,参数数量/顺序不确定的话就用apply。
  2. 考虑可读性:参数数量不多就用call,参数数量比较多的话,把参数整合成数组,使用apply。
  3. 参数集合已经是一个数组的情况,用apply,比如上文的获取数组最大值/最小值。