JavaScript

JavaScript之call、apply、bind

2023-07-20  本文已影响0人  h2coder

前言

在JavaScript中,this指向总是动态的,但也提供了手动改变this指向的方法,那就是call()、applay()和bind(),那么它们之间又有什么区别呢?

Call

语法

fn.call(this, arg1, arg2, arg3...);

示例

// 改变 this 的指向
const obj = {
  name: '八戒',
  say(a, b) {
    console.log(a, b);
    console.log(this);
  }
};
const newObj = {
  name: '悟空'
};
obj.say();// 输出八戒对象本身

// 通过call,改变this指向为 newObj
obj.say.call(newObj, 11, 22);// 输出悟空对象本身

总结

使用call()能改变函数的this,并且马上调用该函数,函数的参数是一个接一个传入

Apply

语法

fn.apply(this, [arg1, arg2, arg3...]);

示例

// 改变 this 的指向
const obj = {
  name: '八戒',
  say(a, b) {
    console.log(a, b);
    console.log(this);
  }
};
const newObj = {
  name: '悟空'
};
// apply的效果和call的效果一致,区别只是传参的方式不同
// apply()的话,参数必须放到数组中,放在第二个参数
// call()的话,参数是放在剩余参数上
obj.say.apply(newObj, [11, 22]);// 输出悟空对象本身

总结

apply()和call()一样,都能改变this指向,也是马上调用该函数,但函数的参数必须放在数组中

Bind

语法

let newFn = fn.bind(this);
newFn(arg1, arg2, arg3...);

示例

// 改变 this 的指向
const obj = {
  name: '八戒',
  say(a, b) {
    console.log(a, b);
    console.log(this);
  }
};
const newObj = {
  name: '悟空'
};
// bind()不会直接调用函数,而是返回一个新函数,但它的this指向已经被修改过了
const fn = obj.say.bind(newObj);
fn(11, 22);

总结

bind()也可以改变函数的this指向,但不会马上调用函数,而是返回一个新函数,函数的参数是在调用返回的新函数时,一个接一个的传入

this的取值

this的取值 不取决于函数的定义,而是取决于怎么调用的(this指向调用者)

应用场景

call的应用场景

// Object.prototype.toString.call(目标变量) 最强大,判断得最准确
// 代码太长,还要严谨地判断字符串结果,建议进行封装来使用
Object.prototype.toString.call(1);//[object Number]
Object.prototype.toString.call('hello');//[object String]
Object.prototype.toString.call(true);//[object Boolean]
Object.prototype.toString.call(null);//[object Null]
Object.prototype.toString.call(undefined);//[object Undefined]
Object.prototype.toString.call([]);//[object Array]
Object.prototype.toString.call({});//[object Object]

apply的应用场景

// apply的应用场景,很像展开运算符,能把数组参数拆开成单个参数来调用
const max = Math.max.call(null, [1, 2, 3]);
// ES6展开运算符,更简洁
// const max = Map.max(...[1, 2, 3]);
console.log(`数组的最大值:${max}`);

bind的应用场景

// bind的应用场景,改变定时器或延时器的this指向
const button = document.querySelector('button');
button.addEventListener('click', function (e) {
  const fn = function () {
    console.log(this);
  };
  // 改变延时器回调函数的this
  setTimeout(fn.bind(this), 1000);
});
上一篇下一篇

猜你喜欢

热点阅读