likes
comments
collection
share

Function.prototype.call()、apply()

作者站长头像
站长
· 阅读数 44

介绍 call()

call()  方法使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数。

参数

  1. thisArg
  • 调用 时要使用的值。如果函数未处于严格模式,null 和未定义将替换为全局对象,并基元值将转换为对象。this func
  1. arg1, …, argN 自选
  • 函数的参数。

返回值

  • 使用指定的值和参数调用函数的结果。this

[传送mdn web docs](Function.prototype.call() - JavaScript | MDN (mozilla.org))

代码示例

let test = {
  name: '123',
  add: function (){
    console.log(`我输出的信息是${ this.name }`);
  }
}
test.add()  // 我输出的信息是123

let test2 = {
   name: '456',
}

// 这里test2对象也想用test对象中的add方法,如何实现?
// 1. 在test2对象中写一个和test对象中相同的方法?
let test2 = {
   name: '456',
   add: function (){
    console.log(`我输出的信息是${ this.name }`);
  }
}
// 这样写的意义何在呢?,所以它来了,它来了

在上例代码中,我们尝试用call方法来实现要求看看

Function.prototype.call()、apply()

Function.prototype.call()、apply() 这样写起来是不是看起来代码又少,不用写重复无用的代码

涉及知识点

  1. JS中this的指向
  2. ES6一些常用语法

需要知道两个前置条件

  • 不管是基本数据类型还是引用数据类型,它们的方法都建立(定义)在原型对象上
  • 方法中的this指向是谁调用这个方法

废话不多说,开始手撕

 // 先定义N个参数,其中第一个参数(target)是即将借用这个函数的对象,剩下的参数用...(扩展运算符)...args表示rest参数
 Function.prototype.myCall = function (target, ...args) {
      // 如果target传入的是一个非真值的对象,则该对象指向window
      target = target || window;
      if(Object.prototype.toString.call(target) === "[Object, Object]") return;
      // 先定义一个Symbol数据类型的变量,防止target对象上面有相同名称的数据变量
      const newSym = Symbol();
      // 这里需要了解一个普通函数中的this是指向调用这个函数的对象的,所以这里需要test对象中的add方法中的this指向调用该方法(add方法)的对象,所以我们要在该对象中去创建一个方法用来改变this的指向,这时谁调用该方法this就指向谁
      target[newSym] = this;
      // 我们已经给target对象上添加了方法,但是什么时候调用呢?调用的时候传入什么参数呢?这也很容易
      // args本身是rest参数,搭配的变量是一个数组,数组解构后就可以一个个传入函数中
      let res = target[newSym](...args); 
      // 当借用函数执行完后需要进行删除,不要留着过年
      delete target[newSym];
      // 该函数方法是有返回值的,所以要将res进行返回
      return res;
 }

代码检测

Function.prototype.call()、apply()

总结

Function.prototype.call(): 本质上就是在借用的函数对象上去添加一个方法,然后执行完后删除

介绍 apply()

apply() 方法调用一个具有给定 this 值的函数,以及以一个数组(或一个类数组对象)的形式提供的参数。

参数

  1. thisArg
  • 在 func 函数运行时使用的 this 值。请注意,this 可能不是该方法看到的实际值:如果这个函数处于非严格模式下,则指定为 null 或 undefined 时会自动替换为指向全局对象,原始值会被包装。
  1. argsArray 可选
  • 一个数组或者类数组对象,其中的数组元素将作为单独的参数传给 func 函数。如果该参数的值为 null 或 undefined,则表示不需要传入任何参数。从 ECMAScript 5 开始可以使用类数组对象。浏览器兼容性请参阅本文底部内容。

[详细传送mdn web docs](Function.prototype.apply() - JavaScript | MDN (mozilla.org))

apply()方法和call()方法区别

本质上它们只是在使用方式上有区别而已,call调用时,从第二个参数开始,是一个个传递进去的,apply调用的时候,第二个参数是个数组而已。

废话不多说,开始手撕

      // apply()方法rest参数必须是Array
 Function.prototype.myCall = function (target, args) {
      // 如果target传入的是一个非真值的对象,则该对象指向window
      target = target || window;
      target[newSym] = this;
      // 解构 args数组
      let res = target[newSym](...args); 
      // 当借用函数执行完后需要进行删除,不要留着过年
      delete target[newSym];
      // 该函数方法是有返回值的,所以要将res进行返回
      return res;
 }

注意

call() 方法接受的是一个参数列表,而 apply() 方法接受的是一个包含多个参数的数组

转载自:https://juejin.cn/post/7177001596004335677
评论
请登录