如何在已经返回值后链接方法?

时间:2013-12-31 02:41:25

标签: javascript

以下工作正常:

//Returns an object with an "id" of 1, which is inside another object, "collection".
//Then, calls .move(), which sets collection's property "coordinates" to {x: 20, y: 20}

collection.get(1).move(20,20);

console.log(collection.get(1).get('coordinates')); //returns { x: 20, y: 20 }

这是有效的,因为集合.get()方法执行返回此;
因此,该方法是可链接的。

然而,这不起作用:

collection.get(1) //returns the object inside "collection" that has an "id" of 1
.get('coordinates') //returns that object's current "coordinates" { x: 20, y: 20 }
.move(20,20); //error

这是因为带有id:1“.get()方法的”对象看起来与此类似:

Thing.prototype = {
    id: null,
    get: function(prop) {
            if (prop == 'id') {
                return this.id; 
            } else {
                return this.attributes[prop];
            }
         } 
    }       

(顺便说一句,当对象Thing被初始化时,id就会被设置。)正如你所看到的,这个单独的.get()方法已经返回一个值(它的对象的某个属性)。
因此,考虑到现在设置代码的方式,该方法是不可链接的。

为了把它包装起来,我的“收藏品”包含了一系列“东西”。每个集合都有一个 .get()方法,它从集合的数组中返回 thing 。此外,每个 thing 都有一个 .get()方法,它从 thing 中的特定属性返回一个值。

我遇到的问题是,如果可能的话,我想制作单独的 thing .get()方法可链接...但是,我无法调用这两行代码同一块:

return this[prop];
return this;

例如,我查看了one of John Resig's slides的代码摘录:

Function.prototype.bind = function(){ 
  var fn = this, args = Array.prototype.slice.call(arguments), object = args.shift(); 
  return function(){ 
    return fn.apply(object, 
      args.concat(Array.prototype.slice.call(arguments))); 
  }; 
};

显示了通过使用回调函数返回一些不同的东西的例子(我认为)。

我已经尝试了几种不同的方法来解决这个问题,但是没有用,包括使用返回对象的回调返回另一个方法的对象。

任何推动正确的方向都将受到赞赏。

3 个答案:

答案 0 :(得分:2)

一个函数只能返回一个东西。如果它的目的是返回关于对象的数据,它也不能返回对象本身。您只能链接用于副作用的方法或返回相关集合。

答案 1 :(得分:0)

如果您只关心对子对象执行操作,您可以查看jQuery的addBackend以获取灵感。也就是说,我不确定它是非常好的API设计;如果你只是将一个中间结果放在一个变量中并使用多个语句,那么用法会更清楚,即使这不是那么“光滑”。

答案 2 :(得分:0)

最重要的是,如果你想保持链条运行,你的函数必须返回对象本身;这是一种方法:

get: function(prop, callback) {
        if (prop == 'id') {
            callback(this.id);
        } else {
            callback(this.attributes[prop]);
        }
        return this;
     }

这使得它可以再次链接,因为数据提取的副作用现在已被隔离,但结果逻辑可能看起来有点滑稽:

collection.get(1)
  .get('coordinates', function(value) {
     // whatever
  })
  .move(20,20);