在javascript中应用参数并不起作用

时间:2014-04-18 15:03:39

标签: javascript promise

我正在尝试创建一个小实用程序函数toPromise,它使用回调将函数转换为promise函数(使用Q)。 这是实用程序:

Object.defineProperty(Function.prototype, "toPromise", {
  enumerable: false,
  configurable: false,
  writable: false,
  value: function(self) {
    var $this;
    $this = this;
    return function() {
      var args, deferred;
      deferred = Q.defer();
      args = arguments;
      args[args.length] = deferred.resolve;
      console.dir(args);
      $this.apply(self, args);
      return deferred.promise;
    };
  }
});

以下是用法:

var f = function(nickname, name, callback){
  console.log(arguments)
  callback(undefined, name+" "+nickname);
};
f.toPromise(this)("a", "b").then(function(str){
  console.log(str)
});

但输出是:

{ '0': 'a', '1': 'b', '2': [Function] } // This is debugging from utils
{ '0': 'a', '1': 'b' } // and from the function f

C:\test.js:4
  callback(undefined, name+" "+nickname);
  ^
TypeError: undefined is not a function

那么为什么第三个arg(在utils中)函数没有传递给apply

2 个答案:

答案 0 :(得分:2)

arguments对象不是真正的数组:

>>> function getArguments() { return arguments; }
>>> var a = getArguments(1,2,3), b = [1,2,3];
>>> a[3] = 4; b[3] = 4;
>>> a
[1, 2, 3]
>>> b
[1, 2, 3, 4]
>>> a.length
3
>>> b.length
4

因此,如果您打算修改它或将其传递到函数外部,最好将其转换为真实数组:

var args = Array.prototype.slice.call(arguments);

答案 1 :(得分:2)

您确实已将回调分配给arguments object,但由于它不是一个不会自动增加其length属性的实际数组。如果length仍为2,则只会在apply中跳过您的回调。

修复很简单:

Function.prototype.toPromise = function(self) {
    var fn = this;
    return function() {
        var deferred = Q.defer();
        arguments[arguments.length++] = deferred.resolve;
//                                ^^
        fn.apply(self||this, arguments);
        return deferred.promise;
    };
};

您也可以使用Array.prototype.push.call(arguments, deferred.resolve)。请注意Q already provides such similar1 a functionality(可能已经优化了效率),所以如果您只是想在原型上使用它,那么最好做

Function.prototype.toPromise = function(self) {
    return Q.nbind(this, self);
};

1:请注意resolve()不接受错误参数,例如" nodebacks"通常做