问:

使用 Function.prototype.apply() 和 Function.prototype.call() 调用函数有什么区别?

var func = function() {alert('hello!');
};

func.apply(); 与 func.call();

上述两种方法之间是否存在性能差异?什么时候最好使用 call 而不是 apply,反之亦然?

答1:

一个优秀的自由职业者,应该有对需求敏感和精准需求捕获的能力,而huntsbot.com提供了这个机会

不同之处在于 apply 允许您使用 arguments 作为数组调用函数; call 要求明确列出参数。一个有用的助记符是 “A 表示 a 射线,C 表示 comma。”

请参阅 MDN 关于 apply 和 call 的文档。

伪语法:

theFunction.apply(valueForThis, arrayOfArgs)

theFunction.call(valueForThis, arg1, arg2, …)

从 ES6 开始,还可以使用 spread 数组与 call 函数一起使用,您可以看到兼容性 here。

示例代码:

function theFunction(name,professional) { console.log(“我叫”+name+“,我是”+professional+“。”); } theFunction(“约翰”, “消防员”); theFunction.apply(undefined, [“Susan”, “学校老师”]); theFunction.call(undefined, “克劳德”, “数学家”); theFunction.call(undefined, …[“Matthew”, “physicist”]); // 与扩展运算符一起使用

要添加的一件事是 args 必须是数字数组 ([])。关联数组 ({}) 将不起作用。

@KevinSchroeder:在 javascript 中,[] 被称为 array,{} 被称为 object。

我经常忘记哪个需要一个数组,哪个需要你列出参数。我曾经记得的一个技巧是,如果方法的第一个字母以 a 开头,那么它需要一个数组,即一个应用数组

@SAM 使用 call 而不是普通的函数调用只有在您需要更改函数调用的 this 值时才有意义。一个示例(将函数参数对象转换为数组):Array.prototype.slice.call(arguments) 或 [].slice.call(arguments)。 apply 如果您在数组中有参数,例如在调用具有(几乎)相同参数的另一个函数的函数中,则 apply 是有意义的。 建议 如果可以满足您的需要,请使用普通函数调用 funcname(arg1),并在您真正需要的特殊场合保存 call 和 apply他们。

@KunalSingh call 和 apply 都有两个参数。 apply' and call 函数的第一个参数必须是所有者对象,第二个参数将分别是数组或逗号分隔的参数。如果您将 null 或 undefined 作为第一个参数传递,那么在非严格模式下,它们将被替换为全局对象,即 window

答2:

HuntsBot周刊–不定时分享成功产品案例,学习他们如何成功建立自己的副业–huntsbot.com

K. Scott Allen 对此有 a nice writeup。

基本上,它们在处理函数参数的方式上有所不同。

apply() 方法与 call() 相同,只是 apply() 需要一个数组作为第二个参数。该数组表示目标方法的参数。”

所以:

// assuming you have f
function f(message) { ... }
f.call(receiver, "test");
f.apply(receiver, ["test"]);

apply() 和 call() 的第二个参数是可选的,不是必需的。

第一个参数也不是必需的。

@Ikrom,第一个参数不是 call 所必需的,而是 apply 所必需的

答3:

一个优秀的自由职业者,应该有对需求敏感和精准需求捕获的能力,而huntsbot.com提供了这个机会

要回答有关何时使用每个函数的部分,如果您不知道要传递的参数数量,或者如果它们已经在数组或类似数组的对象中(如 arguments 对象),请使用 apply转发您自己的参数。否则使用 call,因为不需要将参数包装在数组中。

f.call(thisObject, a, b, c); // Fixed number of argumentsf.apply(thisObject, arguments); // Forward this function's argumentsvar args = [];
while (...) {args.push(some_value());
}
f.apply(thisObject, args); // Unknown number of arguments

当我不传递任何参数时(如您的示例),我更喜欢 call,因为我正在 调用该函数。 apply 表示您正在将该函数应用到(不存在的)参数。

应该没有任何性能差异,除非您使用 apply 并将参数包装在一个数组中(例如 f.apply(thisObject, [a, b, c]) 而不是 f.call(thisObject, a, b, c))。我没有测试过它,所以可能会有差异,但它会非常特定于浏览器。如果您还没有数组中的参数,call 可能会更快,如果有的话,apply 可能会更快。

答4:

huntsbot.com汇聚了国内外优秀的初创产品创意,可按收入、分类等筛选,希望这些产品与实践经验能给您带来灵感。

这是一个很好的助记符。 Apply 使用数组并且总是使用一两个参数。当您使用 Call 时,您必须计算参数的数量。

有用的助记符就在那里!我会将“一个或两个参数”更改为“最多两个参数”,因为 apply 的第一个或第二个参数都不是必需的。我不确定为什么会在没有参数的情况下调用 apply 或 call。似乎有人试图找出这里的原因stackoverflow.com/questions/15903782/…

答5:

huntsbot.com洞察每一个产品背后的需求与收益,从而捕获灵感

虽然这是一个老话题,但我只想指出 .call 比 .apply 稍快。我不能告诉你确切的原因。

参见 jsPerf,http://jsperf.com/test-call-vs-apply/3

[UPDATE!]

Douglas Crockford 简要提到了两者之间的差异,这可能有助于解释性能差异… http://youtu.be/ya4UHuXNygM?t=15m52s

Apply 接受一个参数数组,而 Call 接受零个或多个单独的参数!啊哈哈!

.apply(this, […])

.call(this, param1, param2, param3, param4…)

这取决于函数对参数/数组的作用,如果不需要处理数组,是否需要更少的时间?

有趣的是,即使没有数组,调用仍然要快得多。 jsperf.com/applyvscallvsfn2

@JoshMc 那将是非常特定于浏览器的。在 IE 11 中,我的应用速度是通话速度的两倍。

1. 创建一个新数组意味着垃圾收集器需要在某个时候清理它。 2. 使用解引用访问数组中的项目比直接访问变量(参数)效率低。 (我相信这就是 kmatheny 所说的“解析”,这实际上是完全不同的东西。)但是我的论点都没有解释 jsperf。这必须与引擎对这两个函数的实现有关,例如,如果没有传递,它们可能会创建一个空数组。

感谢您分享测试和视频

答6:

一个优秀的自由职业者,应该有对需求敏感和精准需求捕获的能力,而huntsbot.com提供了这个机会

遵循 Closure: The Definitive Guide by Michael Bolin 的摘录。它可能看起来有点冗长,但它充满了很多洞察力。来自“附录 B. 经常被误解的 JavaScript 概念”:

调用函数时 this 指的是什么

当调用 foo.bar.baz() 形式的函数时,对象 foo.bar 被称为接收者。当函数被调用时,接收者被用作 this 的值:

var obj = {};
obj.value = 10;
/** @param {...number} additionalValues */
obj.addValues = function(additionalValues) {for (var i = 0; i < arguments.length; i++) {this.value += arguments[i];}return this.value;
};
// Evaluates to 30 because obj is used as the value for 'this' when
// obj.addValues() is called, so obj.value becomes 10 + 20.
obj.addValues(20);

如果调用函数时没有明确的接收者,则全局对象成为接收者。如第 47 页的“goog.global”中所述,当 JavaScript 在 Web 浏览器中执行时,window 是全局对象。这导致了一些令人惊讶的行为:

var f = obj.addValues;
// Evaluates to NaN because window is used as the value for 'this' when
// f() is called. Because and window.value is undefined, adding a number to
// it results in NaN.
f(20);
// This also has the unintentional side effect of adding a value to window:
alert(window.value); // Alerts NaN

即使 obj.addValues 和 f 引用相同的函数,它们在调用时的行为也会有所不同,因为接收者的值在每次调用中都不同。因此,在调用引用 this 的函数时,确保 this 在调用时具有正确的值非常重要。需要明确的是,如果函数体中没有引用 this,那么 f(20) 和 obj.addValues(20) 的行为将是相同的。

因为函数是 JavaScript 中的一等对象,所以它们可以有自己的方法。所有函数都有方法 call() 和 apply(),它们可以在调用函数时重新定义接收者(即 this 引用的对象)。方法签名如下:

/**
* @param {*=} receiver to substitute for 'this'
* @param {...} parameters to use as arguments to the function
*/
Function.prototype.call;
/**
* @param {*=} receiver to substitute for 'this'
* @param {Array} parameters to use as arguments to the function
*/
Function.prototype.apply;

请注意,call() 和 apply() 之间的唯一区别是 call() 将函数参数作为单独的参数接收,而 apply() 将它们作为单个数组接收:

// When f is called with obj as its receiver, it behaves the same as calling
// obj.addValues(). Both of the following increase obj.value by 60:
f.call(obj, 10, 20, 30);
f.apply(obj, [10, 20, 30]);

以下调用是等效的,因为 f 和 obj.addValues 指的是同一个函数:

obj.addValues.call(obj, 10, 20, 30);
obj.addValues.apply(obj, [10, 20, 30]);

但是,由于 call() 和 apply() 都没有使用自己的接收者的值来代替未指定的接收者参数,因此以下内容将不起作用:

// Both statements evaluate to NaN
obj.addValues.call(undefined, 10, 20, 30);
obj.addValues.apply(undefined, [10, 20, 30]);

调用函数时,this 的值永远不能是 null 或 undefined。当 null 或 undefined 作为接收器提供给 call() 或 apply() 时,全局对象将用作接收器的值。因此,前面的代码同样具有向全局对象添加一个名为 value 的属性的不良副作用。

将函数视为不知道分配给它的变量可能会有所帮助。这有助于强化这样的想法,即 this 的值将在调用函数时而不是在定义函数时绑定。

提取结束。

请注意,additionalValues 未在 obj.addValues 正文中引用

我知道你在回答这个问题,但想补充一点:你可以在定义 f 时使用 bind。 var f = obj.addValues; 变为 var f = obj.addValues.bind(obj),现在 f(20) 无需每次都使用 call 或 apply 即可工作。

我知道这不是你写的,但你确实强调了书中相关的文字和示例,我非常感激。他们非常有帮助。

答7:

huntsbot.com全球7大洲远程工作机会,探索不一样的工作方式

有时,一个对象借用另一个对象的功能很有用,这意味着借用的对象只是简单地执行借出的功能,就好像它是自己的一样。

一个小代码示例:

var friend = {car: false,lendCar: function ( canLend ){this.car = canLend;}}; var me = {car: false,gotCar: function(){return this.car === true;}
};console.log(me.gotCar()); // falsefriend.lendCar.call(me, true); console.log(me.gotCar()); // truefriend.lendCar.apply(me, [false]);console.log(me.gotCar()); // false

这些方法对于赋予对象临时功能非常有用。

想知道如何查看console.log的人请查看:What is console.log and how do I use it?

答8:

保持自己快人一步,享受全网独家提供的一站式外包任务、远程工作、创意产品订阅服务–huntsbot.com

调用、应用和绑定的另一个例子。 Call 和 Apply 之间的区别很明显,但 Bind 的工作方式如下:

Bind 返回一个可以执行的函数实例 第一个参数是 ‘this’ 第二个参数是逗号分隔的参数列表(如调用)

}

function Person(name) {this.name = name;
}
Person.prototype.getName = function(a,b) { return this.name + " " + a + " " + b;
}var reader = new Person('John Smith');reader.getName = function() {// Apply and Call executes the function and returns value// Also notice the different ways of extracting 'getName' prototypevar baseName = Object.getPrototypeOf(this).getName.apply(this,["is a", "boy"]);console.log("Apply: " + baseName);var baseName = Object.getPrototypeOf(reader).getName.call(this, "is a", "boy"); console.log("Call: " + baseName);// Bind returns function which can be invokedvar baseName = Person.prototype.getName.bind(this, "is a", "boy"); console.log("Bind: " + baseName());
}reader.getName();
/* Output
Apply: John Smith is a boy
Call: John Smith is a boy
Bind: John Smith is a boy
*/

答9:

huntsbot.com全球7大洲远程工作机会,探索不一样的工作方式

我想展示一个示例,其中使用了“valueForThis”参数:

Array.prototype.push = function(element) {/*Native code*, that uses 'this'       this.put(element);*/
}
var array = [];
array.push(1);
array.push.apply(array,[2,3]);
Array.prototype.push.apply(array,[4,5]);
array.push.call(array,6,7);
Array.prototype.push.call(array,8,9);
//[1, 2, 3, 4, 5, 6, 7, 8, 9] 

*详情:http://es5.github.io/#x15.4.4.7

答10:

huntsbot.com全球7大洲远程工作机会,探索不一样的工作方式

Call() 接受逗号分隔的参数,例如:

.call(scope, arg1, arg2, arg3)

并且 apply() 接受一个参数数组,例如:

.apply(scope, [arg1, arg2, arg3])

这里还有几个使用示例:http://blog.i-evaluation.com/2012/08/15/javascript-call-and-apply/

// call() === 逗号分隔的参数 (arguments-list) .call(this, args1, args2, args3, ...) // apply() === 参数数组 (array-items) .应用(这个,[arr0,arr1,arr2,...])

答11:

huntsbot.com – 高效赚钱,自由工作

从 the MDN docs on Function.prototype.apply() :

apply() 方法使用给定的 this 值和作为数组(或类似数组的对象)提供的参数调用函数。语法 fun.apply(thisArg, [argsArray])

从 the MDN docs on Function.prototype.call() :

call() 方法使用给定的 this 值和单独提供的参数调用函数。语法 fun.call(thisArg[, arg1[, arg2[, …]]])

从 Function.apply and Function.call in JavaScript :

apply() 方法与 call() 相同,只是 apply() 需要一个数组作为第二个参数。该数组表示目标方法的参数。

代码示例:

var doSomething = function() { var arr = []; for(i in arguments) { if(typeof this[arguments[i]] !== ‘undefined’) { arr.push(this[arguments[i]]); } } 返回 arr; } var output = function(position, obj) { document.body.innerHTML += 'output ’ + position + ‘’ + JSON.stringify(obj) + ‘\n\n< br><小时>’; } 输出(1,doSomething(“一”,“二”,“二”,“一”));输出(2,doSomething.apply({一:‘史蒂文’,二:‘简’},[‘一’,‘二’,‘二’,‘一’]));输出(3,doSomething.call({一个:‘史蒂文’,两个:‘简’},‘一个’,‘两个’,‘两个’,‘一个’));

另见this Fiddle。

打造属于自己的副业,开启自由职业之旅,从huntsbot.com开始!

原文链接:https://www.huntsbot.com/qa/yOnr/what-is-the-difference-between-call-and-apply?lang=zh_CN&from=csdn

huntsbot.com高效搞钱,一站式跟进超10+任务平台外包需求

call 和 apply 和有什么不一样?相关推荐

  1. Kotlin let、with、run、apply、also函数的使用

    let,with,run,apply,also 是内联扩展函数 下面是自己使用的心的如果有错的地方希望给予指正谢谢 这几个主要用来简化操作,使得代码可读性提高 ,下面列举项目中使用效果 1 let 先 ...

  2. JS中的call()方法和apply()方法用法总结

    1. 每个函数都包含两个非继承而来的方法:call()方法和apply()方法. 2. 相同点:这两个方法的作用是一样的. 都是在特定的作用域中调用函数,等于设置函数体内this对象的值,以扩充函数赖 ...

  3. python dataframe取某行某列_pandas dataframe.apply() 实现对某一行/列进行处理获得一个新行/新列...

    重点: dataframe.apply(function,axis)对一行或一列做出一些操作(axis=1则为对某一列进行操作,此时,apply函数每次将dataframe的一行传给function, ...

  4. Angular的ChangeDetectorRef.detectChanges()实现angularJS的$apply()方法,强制刷新数据渲染

    在Javascript代码里,都是按照一定顺序来执行的,当轮到一个代码片段执行的时候,浏览器就只会去执行当前的片段,不会做任何其他的事情.所以有时候一些做得不是很好的网页,当点击了某个东西之后会卡住, ...

  5. javascript的call()方法与apply()方法的理解

    先看一段代码 function cat() {} cat.prototype={food:'fish',say:function () {console.log('I love '+this.food ...

  6. 函数的四种调用模式.上下文调用.call.apply

    闭包:函数就是一个闭包,一个封闭的作用域; 返回函数,要返回多个函数就用一个对象封装一下, 立即执行函数+return 回调函数 JS动态创建的DOM,不会被搜索引擎抓取,对SEO不友好. /*win ...

  7. 微信小程序之apply和call ( 附示例代码和注释讲解) apply call  bind

    微信小程序开发交流qq群   173683895 相同点:作用是一样的,它们能劫持另外一个对象的方法,继承另外一个对象的属性: js中的call(), apply()和bind()是Function. ...

  8. apply call bind 简介

    Function.prototype.call(thisArg [, arg1, arg2, ...]) call() 简述 call() 方法 调用一个函数, 其具有一个指定的 this 值和分别地 ...

  9. The Apply method of function object

    2019独角兽企业重金招聘Python工程师标准>>> http://webreference.com As explained in the previous page, Java ...

  10. JS学习笔记之call、apply的用法

    1.call和apply的区别 call和apply唯一的区别是传入参数的形式不同. apply接受两个参数,第一个参数指定了函数体内this对象的指向,第二个参数为一个带下标的集合,可以是数组,也可 ...

最新文章

  1. pythonista3使用说明_Pythonista中文文档:sound
  2. vue 源码学习(一) 目录结构和构建过程简介 1
  3. WORD如何隐藏选中内容?
  4. 【学习率调整】学习率衰减之周期余弦退火 (cyclic cosine annealing learning rate schedule)
  5. 华中数控预计继续亏损 拟靠关联交易增收存疑
  6. 计蒜之道2015程序设计大赛初赛第三场——腾讯手机地图
  7. 使用BigDecimal时,报NumberFormatException
  8. UVA11021 Tribles
  9. opboot怎么刷入固件_OPPO手机怎么进行系统(固件)升级?(附四种方法)
  10. android人脸抠图,人脸框抠图如何实现
  11. java使字符串转二维码
  12. linux c 删除文件,linux c remove 删除文件或目录函数
  13. Linux查找之find/df/du命令
  14. Distributed System 基础(四)隐私性(Privacy)
  15. 领导驾驶舱大数据平台的实施流程
  16. EPS创建三维模型-(osgb数据在EPS中的转换数据)
  17. 是谁在为加速网络智能化落地打造开放、融合、端到端平台?
  18. 软件自动化测试——入门、进阶与实战
  19. a类计算机期刊,中国计算机学会推荐国际学术刊物(人工智能与模式识别)
  20. 如何把小米和计算机共享,小米盒子局域网共享方法 Windows7系统共享图文教程

热门文章

  1. 得力科学计算机换电池,就地取材,简单拆解维修得力小闹钟
  2. 史上最强网推案例,没有之一【ZW团队实战经典】
  3. 7月1日Java学习
  4. Spring Boot 启动 Logo 修改 字符图案 只支持ASCII字符
  5. 嘀嗒拼车成为全国首家获得政府备案的合乘平台
  6. 输出1000-2000内的闰年
  7. 2021年危险化学品经营单位主要负责人模拟考试题库及危险化学品经营单位主要负责人考试试题
  8. 湖南大学超级计算机天河,基础科学研究
  9. 利用 bioconda 管理生物信息软件
  10. 七个简单步骤撰写课程论文(academic essay)