【问题标题】:Why is function(global, factory) used in so many JS libraries?为什么这么多 JS 库中使用 function(global, factory)?
【发布时间】:2020-02-23 17:44:19
【问题描述】:

在许多 JavaScript 库中,我将 global, factory 视为函数的参数。
例如:

jQuery

( function( global, factory ) {

    "use strict";

    if ( typeof module === "object" && typeof module.exports === "object" ) {
//...

Vue.js

(function (global, factory) {
  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
  typeof define === 'function' && define.amd ? define(factory) :
  (global = global || self, global.Vue = factory());
}(this, function () { 'use strict';

  /*  */

// ...

可能还有更多的例子......

我的问题是:为什么globalfactory 经常被用作参数,它们是什么?

【问题讨论】:

  • 这些特定名称可能是某些模块捆绑器的输出,但请查找“JavaScript UMD”作为一个好的起点。
  • 这是UMD pattern 标头
  • 您缺少一些代码来完全解释 jQuery,但您可以清楚地看到 factoryfunction () { 'use strict'; /* */ ...
  • @slebetman 恐怕我听不懂你想说什么。
  • 您可以在自己的代码示例中看到,globalthisfactoryfunction () {...。代码声明了一个函数,为了我们的目的,让我们给它一个名字foo - function foo (global, factory) {...}。然后它称它为foo(this, function () { 'use strict' ...。但它这样做并没有像我们那样给它一个名字,所以它看起来像这样:(function (global, factory) {...}( this, function () {'use strict'; ...})。它基本上是一个 IIFE

标签: javascript


【解决方案1】:

正如cmet中的几个人所说,真正的答案是,这是UMD模块的结构。

我之所以写这个作为答案,主要是因为很难在 cmets 中说明这一点。但是您可以清楚地看到您的 Vue.js 示例中的代码在做什么:

    ┌──────────────────┐       ┌──────────────────┐
    │                  ▼       ▼                  │
    │    (function (global, factory) {            │
    │                                             │
    │                                             │
    │        /* deleted for clarity */            │
    │                 ┌───────────────────────────┘
    │                 │
    │    }(this, function () { 'use strict';
    │       │
    └───────┘
             /* */

         })

所以基本上它是一个IIFE。如果你给匿名函数命名,你可以更清楚地重写这个结构:

// rename function () { 'use strict' ...
function Vue () { 'use strict';
    /* */
}

// rename function (global, factory) ...
function UMD (global, factory) {
    /* deleted for clarity */ 
}

UMD(this, Vue);

所以global 基本上是this,当从任何函数外部引用它时,它指向全局对象(浏览器中的window,而不是在node.js 中命名),factory 是一个创建 Vue 的函数.js 对象(如果是 jQuery,则为 jQuery)。基本上factory是库的实现。

这种结构的编写方式不会在全局范围内创建任何不必要的变量或函数,从而避免污染全局范围并避免变量/函数名称与其他库冲突。

至于为什么将this分配给global?那是因为window 是(是?)全局范围内完全不受保护的变量(这就是为什么 node.js 没有给它命名)并且任何第 3 方代码都可以用不同的东西覆盖它或修改它。如果您在使用未知的 3rd 方代码时想要浏览器的原始全局对象,则需要使用此 this 技巧。

【讨论】:

  • 谢谢,这很有意义。
  • 感谢您的精彩解释,您能解释一下您最后一段的更多内容吗?你怎么还能用this这个把戏得到原来的全局obj,如果window已经被污染了,那么this也会被污染吧?如果我们想传入window,重命名的代码不应该变成UMD(window, Vue);吗?
  • @Zennichimaro 不完全是。全局对象是一个内部 C++ 构造。在 Rhino 和 Nodejs 等环境中,全局对象没有名称。在浏览器中,window 变量是指向全局对象的指针。现在,浏览器可以将其设为常规指针,因此修改 window 会修改全局对象,但看起来 window 只是继承自全局对象。例如,如果您替换 window.getElementById()this 技巧将获得原始的 getElementById() 函数,因为 getElementById() 实际上是一个全局函数,而不仅仅是 window 的属性
  • @Zennichimaro 基本上,有一个 C++ 内部作为对象实现的作用域机制,全局作用域是 C++ 全局对象。 Javascript 将全局范围的所有成员(以及对象)暴露给 window 变量(它本身属于全局范围)。看起来 window 没有在 C++ 内部用于表示全局范围。
【解决方案2】:

我创建了小库以便 slebetman answare 更好地理解

   (function (global, factory) {            
    typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
    typeof define === 'function' && define.amd ? define(factory) :
    global.tinylib= factory();         

    } (this,function() {

// your code shoud place here
    }))

例如:这很简单,我创建了库

(function (global, factory) {            
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = 
factory() :
    typeof define === 'function' && define.amd ? define(factory) :
    global.tinylib = factory();         

    } (this,function() {
 -----------------------------------------mylibrary code start------------------    
 var tinylib= (function(el) {
 var obj={}
 var myelement=el

 obj.setColor=(color)=>{
 myelement.style.color=color;
  }
    return obj;
 -----------------------------------------mylibrary code end------------------    

  })
 return tinylib;
    }))

创建库的使用

import {tinylib} from 'tinylib'

初始化:

var lib=tinylib(document.getElementById('color')) //now we use lib variable whenever we want to invoke example showen below

用法:

lib.setColor('red')

【讨论】:

    猜你喜欢
    • 2011-11-27
    • 2012-05-02
    • 2011-03-30
    • 2013-06-06
    • 2012-06-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-06
    相关资源
    最近更新 更多