我遇到了一个有趣的情况,涉及Java脚本闭包和数组。
我不确定javascript的哪一部分导致了arguments数组的缓存。



var SLICE = Array.prototype.slice;

  var attach = function(method) {
    var args = SLICE.call(arguments, 1);
    return function() {
      args = args.concat(SLICE.call(arguments, 0));
      method.apply(null, args);
    };
  };

  function foo(param1, param2, param3) {
    console.log(param1, param2, param3);
  };

  var bar = attach(foo, 1, 2);
  bar(3);
  bar(4);





上面代码的输出是

1 2 3
1 2 3


代替

1 2 3
1 2 4


如果将代码更改为,则将获得正确的输出



var SLICE = Array.prototype.slice;

  var attach = function(method) {
    var args = SLICE.call(arguments, 1);
    return function() {
      method.apply(null, args.concat(SLICE.call(arguments, 0)));
    };
  };

  function foo(param1, param2, param3) {
    console.log(param1, param2, param3);
  };

  var bar = attach(foo, 1, 2);
  bar(3);
  bar(4);





输出是

1 2 3
1 2 4


我想了解,发生这种情况的原因是Java脚本的哪个属性?

编辑:
已对代码进行编辑以删除按钮,并更好地解释场景

最佳答案

foo函数仅接受三个参数,

function foo(param1, param2, param3) {


而且只有三个

method(args[0], args[1], args[2]);


但是,push()会推送到数组,所以当您拥有[1,2,3,4]时,只会发送前三个,而不发送第四个。

该函数接受了四个参数



var SLICE = Array.prototype.slice;

var attach = function(method) {
    var args = SLICE.call(arguments, 1);

    return function() {
        for (var key in arguments) {
            args.push(arguments[key]);
        }
        method(args[0], args[1], args[2], args[3]);
    };
};

function foo(param1, param2, param3, param4) {
    console.log(param1, param2, param3, param4);
};

var bar = attach(foo, 1, 2);
bar(3);
bar(4);





您将在控制台中得到1 2 3 4

换句话说,这与缓存无关,或者没有添加值,只是在将新值推送到数组时,该函数无法接受足够的参数。

更好的方法是接受任意数量参数的函数



var SLICE = Array.prototype.slice;

var attach = function(method) {
    var args = SLICE.call(arguments, 1);

    return function() {
        args = args.concat( SLICE.call(arguments) );
        method.apply(null, args)
    };
};

function foo() {
    console.log(arguments);
};

var bar = attach(foo, 1, 2);
bar(3);
bar(4);





问题中第二个代码片段没有不断添加到数组中的原因是因为未存储该数组,所以concat返回一个新数组,它不会更改原始数组,因此必须

args = args.concat(array);


存储更改。由于您没有存储更改,因此每次调用内部函数时,它都会使用原始数组[1,2]并向其中添加一个值,然后将其返回。

因为未存储,所以第一次调用bar(3)时需要使用[1,2]并添加3,最后得到[1,2,3]
下次调用该函数时,它将执行相同的操作,并使用[1,2]并加4等,最后得到的是[1,2,4]

关于javascript - 为什么此JavaScript闭包数组保留旧值,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/35755617/

10-13 07:47
查看更多