4

我很好奇_.chaining函数是如何实现的,以及它是如何(或者更好地,为什么)以它的方式工作的。

特别是我的问题是每个函数的包装发生在哪里。假设我正在使用_.chain(someArray).filter(...);当我进入该函数时,我可以看到过滤器函数已转换为类似

function () { 
     var args = [this._wrapped]; //the data from chain(...)
     push.apply(args, arguments); //push to the (?) array
     return result.call(this, func.apply(_, args)); //?? where are these coming from?
}

我可以看到该函数在其范围内有 3 个闭包(将其与未链接的函数进行比较,该函数显示函数的定义,而没有对其原始函数的所有闭包)

使用链功能后的作用域

第一个是find 函数本身,第二个是“对对象本身的安全引用”,第三个是下划线类本身。

调用时_.chain(),如何以及在哪里(代码方面)进行转换(创建范围等)。我理解了

//http://underscorejs.org/docs/underscore.html#section-139
 _.chain = function(obj) {
    return _(obj).chain();
  };

被调用,这去

//http://underscorejs.org/docs/underscore.html#section-145
//...
 chain: function() {
      this._chain = true;
      return this;
    },
//...

然后我被卡住了。我无法弄清楚从那里会发生什么。我假设魔法发生在构造函数内部,但我似乎无法弄清楚闭包的额外创建从何而来。所有函数本身都没有显示任何被包装的迹象,链调用看起来没有就像它包裹了一些东西。result似乎在那里,但我不知道它来自哪里。那么,这是在哪里以及如何发生的呢?

4

1 回答 1

0

_.chain(obj) returns new instance of _ with attribute _chain = true, that instance of _ has a _wrapped attribute set to current object (great work here). _.mixin(_) in line #1210 add all of underscore methods to underscore (constructor). _.mixin method replace and extend _ methods (still has the parent functions! Accessible via _.prototype). _.mixin change functions of that _ instance (this is the place you see that new function).

New function is:

function () {
  var args = [this._wrapped];
  push.apply(args, arguments);
  return result.call(this, func.apply(_, args));
}

(doesn't matter what method it is, same for all, func is referenced to the original method)

result method function is :

var result = function(obj) {
  return this._chain ? _(obj).chain() : obj;
};

so if the object returned by func.apply(_, args) has _chain (_.chain set that attribute) returns _(obj).chain() then you can use it again :)

This is process of chaining but what about prototypes!

In constructor function :

var _ = function(obj) {
  if (obj instanceof _) return obj;
  if (!(this instanceof _)) return new _(obj); // This line do the magic
  this._wrapped = obj;
};

Consider this :

func = function(a){this.a = a;}
b = func(2);
b.a // TypeError: Cannot read property 'a' of undefined
c = new func(2);
c.a // returns 2, whooa this the magical javascript!

Read this (Underscore docs about OOP) if you want to learn more about underscore mixin function

Am I missing something?

于 2013-10-16T22:51:23.927 回答