我打开了一个名为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
来回忆所有关于此类方法的私有和公共函数的讨论,但有些事情让我很困惑:
为什么外部匿名函数有参数以及它们将在何处使用?
而不是(function(){//put my code here...}());
作者使用(function(root, factory){//some code...}(this, function(){//main code here...}));
,为什么会这样?
问题(2)我可以看到两个参数this
和function(){//main code here...}
作为参数传递给外部匿名函数,而不是root
和factory
。所以,root
成了this
!但是,现在this
指的是哪里?
也许我们可以更好地重写这一切与否? 我刚刚阅读How do I declare a namespace in JavaScript?,我发现Jaco Pretorius回答得非常好,我可以重写这个并将其添加到我的命名空间,如下所示:
(函数(myGibberishAES){
//主要代码在这里......
}(window.myGibberishAES = window.myGibberishAES || {}));
这是否可以接受可接受的编码标准?
谢谢!
答案 0 :(得分:2)
这种格式称为UMD(通用模块定义),它是一种编写可以使用和不使用AMD(异步模块定义)以及使用和不使用Node的代码的方法。
在第一个匿名函数中,代码正在检查我们所处的环境。
exports
函数,那么我们可能正在使用node.js define
的函数,并且它有一个名为amd
的属性,那么这意味着我们正在使用AMD。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.js
和amdWeb.js
的更简单变体的组合) ,还要看AMD on requireJS。