重写并添加到我的命名空间一个javascript库



我打开了一个名为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");

我可以看到一个最外面的自执行函数返回一个对象,在代码的末尾实际上是匿名的(!),这个对象的成员是自执行函数内部定义的函数,所以,属性"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. 也许我们可以实现一个更好的重写这一切吗?我刚刚读了如何在JavaScript中声明命名空间?我发现Jaco Pretorius的答案非常棒,所以我可以重写这个并将其添加到我的命名空间,像这样:

    (函数(myGibberishAES) {

    //主代码

    }(窗口。myGibberishAES =窗口。myGibberishAES || {}));

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

谢谢!

这种格式被称为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的简单变体的组合),也可以查看AMD的requireJS。

最新更新