Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

underscore链式操作 #3

Open
xlshen opened this issue Mar 15, 2018 · 1 comment
Open

underscore链式操作 #3

xlshen opened this issue Mar 15, 2018 · 1 comment
Assignees
Labels
enhancement New feature or request

Comments

@xlshen
Copy link
Owner

xlshen commented Mar 15, 2018

underscore链式操作

涉及函数:_.chain(obj) === _(obj).chain()

实例:

  // 非 OOP 链式调用
  _.chain([1, 2, 3])
  .map(function(a) {return a;})
  .reverse()
  .value(); // [3, 2, 1]

  // OOP 链式调用
  _([1, 2, 3])
  .chain()
  .map(function(a){return a;})
  .first()
  .value(); // 1

解析:

以上两种方式都可以达到链式调用的目的。在underscore内部实现中,这两种方式实现都是用了OOP的实现方法,具体来看实现函数:

  _.chain = function(obj) {
    var instance = _(obj);
    instance._chain = true;
    return instance;
  };

_.chain(obj)通过调用chain()方法将_(obj)先转化为_的实例对象,然后将实例对象添加_chain属性,返回该实例对象。
【注:对于_(obj)不熟悉的可以移步
underscore中_是弄啥的

而对于_(obj).chain()来说,首先通过_(obj)创建_的实例对象,然后该实例调用_对象原型中的chain()方法【该方法通过_.mixin()方法混入到_.prototype中】详见:underscore中OOP思想—实例对象方法调用实现机制

_.prototype['chain']方法最后一步:

  // _.mixin()方法中_.prototype[name] = function() {...}最后返回
  return chainResult(this, func.apply(_, args));
  // chainResult实现函数
  var chainResult = function(instance, obj) {
      return instance._chain ? _(obj).chain() : obj;
  };

chainResult(this, func.apply(_, args))方法中this_对象,func.apply(_, args)调用_.chain()方法返回传入对象的实例,在上面例子中就是[1, 2, 3]对象的实例对象,并给该对象添加_chain属性,返回该实例对象。此时调用为chain(_对象, [1, 2, 3]添加了_chain属性的实例对象)_._chain === undefined所以直接返回添加了_chain属性的[1, 2, 3]对象实例。

到这里是不是发现了什么?!Yes,_.chain(obj)_(obj).chain()回到了同一起跑线!

最后再梳理一下其中逻辑:chainResult实现函数通过传入的obj实例和obj对象,判断如果obj实例中含有_chain属性则继续调用_(obj).chain()生成具有_chain属性的obj实例对象;如果没有,则说明obj本身已经有了_chain属性【因为调用该函数的都是在_.prototype[XXX]中,该函数的执行最后必然会调用上面说的chainResult方法,func.apply(this, args)最终返回的一定是带有_chain属性的实例对象】,直接返回obj即可。

@Yan2603
Copy link

Yan2603 commented Feb 21, 2022

你好,可否解释一下什么是OOP链式,什么不是OOP链式?使用underscore一般都是_.flatten([1,2,[3,4]])或者_.chain([1,2,[3,4]]).flatten().value()吧,你说的_([1,2,[3,4]])是源码才有的吧

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants