[关闭]
@omg-two 2017-03-11T09:12:13.000000Z 字数 1464 阅读 2033

apply() 以及 call()的使用

JavaScript


语法

两者都是Function.prototype的方法,使用语法如下:

  1. //call的使用
  2. fun.call(thisArg[, arg1[, arg2[, ...]]])
  3. //apply的使用
  4. fun.apply(thisArg[, argsArray])

其中,thisArg指的是函数fun运行时的this值,即指定函数运行时的执行上下文。值得注意的是,当非严格模式下,指定null或者undefined时,会自动指向全局对象(浏览器中则是window对象),同时值为原始值(数字,字符串,布尔值)的 this 会指向该原始值的自动包装对象。

两者的主要区别在于之后的参数,其中call接收的是一组参数列表,apply接收的是一个数组或者类数组对象,如果为null或者undefined则表示不需要接受参数。

使用案例

  1. //call的使用案例
  2. var animals = [
  3. {species: 'Lion', name: 'King'},
  4. {species: 'Whale', name: 'Fail'}
  5. ];
  6. for (var i = 0; i < animals.length; i++) {
  7. (function (i) {
  8. this.print = function () {
  9. console.log('#' + i + ' ' + this.species + ': ' + this.name);
  10. }
  11. this.print();
  12. }).call(animals[i], i);
  13. }
  14. //apply的使用案例
  15. /* min/max number in an array */
  16. var numbers = [5, 6, 2, 3, 7];
  17. /* using Math.min/Math.max apply */
  18. var max = Math.max.apply(null, numbers); /* This about equal to Math.max(numbers[0], ...) or Math.max(5, 6, ..) */
  19. var min = Math.min.apply(null, numbers);
  • 注意,apply中的第二个参数如果是arguments对象作为输入,或者其他局部变量,那么它可以表示被调用对象的未指定的参数,被调用对象接下来就会处理所有的这些参数。

思考题

问题

实现一个函数,运算结果可以满足如下预期结果:

  1. add(1)(2) // 3
  2. add(1, 2, 3)(10) // 16
  3. add(1)(2)(3)(4)(5) // 15

答案

*参考代码

  1. function add () {
  2. //将argument转换成数组
  3. var args = Array.prototype.slice.call(arguments);
  4. var fn = function () {
  5. //拼接多次调用的参数为数组
  6. var arg_fn = Array.prototype.slice.call(arguments);
  7. //递归调用add
  8. return add.apply(null, args.concat(arg_fn));
  9. }
  10. //最后一次返回fn时,自动调用valueOf
  11. fn.valueOf = function () {
  12. return args.reduce(function(a, b) {
  13. return a + b;
  14. })
  15. }
  16. return fn;
  17. }
  • 思路流程
    1. 利用闭包传递参数,将参数每次调用中拼接成长数组。
    2. 改写valueOf函数,最后一次返回的fn,会自动调用valueOf函数,从而输出计算和。

直接返回函数名,那么函数会自动调用valueOf进行返回,如果没有valueOf,则会调用toString。某种程度上,弱类型语言的隐式类型转换的锅?

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注