【问题标题】:rewrite and add to my namespace a javascript library重写并添加到我的命名空间一个 javascript 库
【发布时间】:2013-04-13 03:56:27
【问题描述】:

我打开了一个名为 Jibberish (https://github.com/mdp/gibberish-aes) 的 javascript 项目,我试图了解它的编码风格,我只给出了它的开始和结束的一部分:

(function (root, factory) {
    if (typeof exports === 'object') {
        // Node. 
        module.exports = factory();
    } else if (typeof define === 'function' && define.amd) {
        // AMD. Register as an anonymous module.
        define(factory);
    } else {
        // Browser globals (root is window)
        root.GibberishAES = factory();
    }
}(this, function () {
    'use strict';
    var Nr = 14,
    /* Default to 256 Bit Encryption */
    Nk = 8,
    Decrypt = false,
    enc_utf8 = function(s)
    {
        try {
            return unescape(encodeURIComponent(s));
        }
        catch(e) {
            throw 'Error on UTF-8 encode';
        }
    },
    //...................................
    return {
        "size": size,
        "h2a":h2a,
        "expandKey":expandKey,
        "encryptBlock":encryptBlock,
        "decryptBlock":decryptBlock,
        "Decrypt":Decrypt,
        "s2a":s2a,
        "rawEncrypt":rawEncrypt,
        "rawDecrypt":rawDecrypt,
        "dec":dec,
        "openSSLKey":openSSLKey,
        "a2h":a2h,
        "enc":enc,
        "Hash":{"MD5":MD5},
        "Base64":Base64
    };
}));

只是想知道它的用法:

// GibberishAES.enc(string, password)
// Defaults to 256 bit encryption
enc = GibberishAES.enc("This sentence is super secret", "ultra-strong-password");
alert(enc);
GibberishAES.dec(enc, "ultra-strong-password");

我可以看到一个最外层的自执行函数在代码末尾返回一个对象,它实际上是匿名的(!),并且这个对象的成员是在 self-执行函数so,属性"size"引用function size()定义为函数表达式:

size = function(newsize){...}

我什至可以通过将所有返回的函数调用为public 并将其余函数调用为private 来回忆有关这种方法的私有和公共函数的所有讨论,但有些事情让我很困惑:

  1. 为什么外部匿名函数有参数,它们将在哪里使用?

  2. 作者使用(function(root, factory){//some code...}(this, function(){//main code here...}));而不是(function(){//put my code here...}());,这是为什么呢?

  3. 关于问题 (2) 我可以看到两个参数 thisfunction(){//main code here...} 作为参数传递给外部匿名函数,而不是 rootfactory。所以,root 变成了this!但是,现在this 指的是哪里?

  4. 也许我们可以更好地重写这一切? 我刚刚阅读了How do I declare a namespace in JavaScript?,我发现 Jaco Pretorius 的答案非常棒,我可以重写这个并将其添加到 my namespace 中,如下所示:

    (函数(myGibberishAES){

    //这里的主要代码...

    }(window.myGibberishAES = window.myGibberishAES || {}));

这符合可接受的编码标准吗?

谢谢!

【问题讨论】:

  • ...在同一个帖子 (stackoverflow.com/questions/881515/…) 将 Jaco Pretorius 的答案与 Fentex 结合起来,我可以更有创意:mynamespace = window.mynamespace || {}; 然后mynamespace.GibberishAES = (function(){//main code here..}()); 或者我可以做得更好???

标签: javascript javascript-namespaces


【解决方案1】:

这种格式称为 UMD(通用模块定义),它是一种编写代码的方式,可以使用和不使用 AMD(异步模块定义),以及使用和不使用 Node。

在第一个匿名函数中,代码正在检查我们所处的环境。

  1. 如果定义了 exports 函数,那么我们可能正在使用 node.js
  2. 如果有一个名为define的函数,并且它有一个名为amd的属性,那么这意味着我们正在使用AMD。
  3. 如果上述情况都不成立,我们没有使用任何东西,所以我们应该将它附加到根对象,在这种特殊情况下将是 window

这个函数的参数是this(将是window)和一个基本上是一个工厂的函数,也就是说,它是实际定义你的对象的代码。通常(没有 UMD),它看起来像这样:

var myModule = (function() {
    ...
}();

所以现在factory 基本上就是这个函数,它返回你的模块/对象。如果你使用 node.js,这个对象可以分配给module.exports,或者如果你使用 AMD,它可以被传递给define 函数,否则你可以简单地将它附加到根对象(window )。

就您的重写问题而言,您可能不想这样做,因为常规的 JavaScript 命名空间声明模式不适用于 node.js 和 AMD。与 requireJS 一起使用的 AMD 允许您指定和管理依赖项,因此如果有人使用 requireJS,这允许他们非常轻松地导入此模块。这基本上是满足三种不同用例和框架的一种方式。

如果你没有使用node.js或requireJS,你不需要重写任何东西,因为GibberishAES将是一个全局对象,附加到window,所以你可以直接使用它。

有关更多信息,请查看 GitHub 上的 UMD,它有一堆模式(您正在查看的是 nideAdapter.jsamdWeb.js 的更简单变体的组合),还可以查看 @ 987654322@.

【讨论】:

  • 我之前没有使用过 node.js 或 requireJS,但我可以看出这个项目旨在(和)在客户端部分工作,即在用户的浏览器上进行算术运算! this 指的是全局命名空间中的window,谢谢提醒!
  • @centurian 当我第一次遇到这种模式时,我也很困惑。我有一个自己的开源项目,最近有一位贡献者对其进行了修改以支持 AMD。那是我熟悉这种模式的时候。 :)
猜你喜欢
  • 1970-01-01
  • 2013-07-19
  • 1970-01-01
  • 2012-06-20
  • 1970-01-01
  • 1970-01-01
  • 2013-01-11
  • 2017-01-18
  • 2011-03-04
相关资源
最近更新 更多