Function.prototype.call()、apply()
介绍 call()
call()
方法使用一个指定的 this
值和单独给出的一个或多个参数来调用一个函数。
参数
thisArg
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方法来实现要求看看
这样写起来是不是看起来代码又少,不用写重复无用的代码
涉及知识点
- JS中this的指向
- 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()
apply()
方法调用一个具有给定 this
值的函数,以及以一个数组(或一个类数组对象)的形式提供的参数。
参数
thisArg
- 在
func
函数运行时使用的this
值。请注意,this
可能不是该方法看到的实际值:如果这个函数处于非严格模式下,则指定为null
或undefined
时会自动替换为指向全局对象,原始值会被包装。
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