Skip to content

Instantly share code, notes, and snippets.

@Gaubee
Last active March 1, 2018 03:04
Show Gist options
  • Save Gaubee/5014033 to your computer and use it in GitHub Desktop.
Save Gaubee/5014033 to your computer and use it in GitHub Desktop.
javascript(ES3)实现闭包共享(namespace 简单版,可分文件编辑,并整合输出,不污染全局变量),通过闭包实现。 注:Compression函数用于提取代码中的变量。由于JS无块作用域,Compression并不提取块作用域中的变量,为了简化代码,也算是一个Bug。
var log = console.log;
//泳衣格式化代码的正则表达式
var reg = {
DoubleQuotedString : new RegExp('"(?:\\.|(\\\\\\")|[^\\""\\n])*"','g'),//双引号字符串
SingleQuotedString : new RegExp("'(?:\\.|(\\\\\\')|[^\\''\\n])*'",'g'),//单引号字符串
Chars : new RegExp('([(=[{])','g'),//需用空格隔开的字符(用以逻辑判断代码规则)
Empty : new RegExp('[ ]+','g'),//空字符
MultiLineCComments : new RegExp('/\\*[\\s\\S]*?\\*/', 'gm'),//多行注释
SingleLineCComments : new RegExp('//.*$', 'gm'),//单行注释
}
//直接通过语法规则过滤关键字
//keyWord = ["break", "case", "catch", "continue", "default", "delete", "do", "else", "finally", "for", "function", "if", "in", "instanceof", "new", "return", "switch", "this", "throw", "try", "typeof", "void", "while", "with"].toString();
var Compression = function(code){
"use strict";
code = code.toString().replace(reg.DoubleQuotedString,"\"\"")
.replace(reg.SingleQuotedString,"\'\'")
.replace(reg.MultiLineCComments,"")
.replace(reg.SingleLineCComments,"")
.replace(reg.Chars," $1 ")//格式化字符串
.replace(reg.Empty," ");
var lines = code.split("\n"),result;
//#压缩代码
for (var i=0,len = lines.length ;i<len ; ++i)
{
lines[i] = Compression.Trim(lines[i]);//全部收缩一边以便判断
}
//第一行特殊化,去除function()
var firstLine = lines[0].substring(9);
for (var i=0,len = firstLine.length,end;i<len ; ++i)
{
if (firstLine.charAt(i)==='('){
end++;
}else if (firstLine.charAt(i)===')'){
if(!--end){
lines[0] = firstLine.substring(1+i);
}
}
}
var chars1 = ".,{[";//可跨行编辑的首字符
var chars2 = ".,";//可跨行编辑尾字符,进行合并行
for (var i=0,j=0,len = lines.length-1;i<len ; ++i)
{
var str = lines[i],next = lines[j=i+1];
if (str){
if (next===""){
for (++j;j<len ; ++j)
{
if(next = lines[j])break;
}
}
//log("now:"+str);
//log("next:"+next);
var last = str.charAt(str.length-1);
//log(chars2.indexOf(last));
if ( last!== ';'){
if (chars2.indexOf(last) !== -1){
lines[i] += next;
//log(lines[j] +"!!!!")
lines[j] = "";
}else
if (chars1.indexOf(next.charAt(0)) === -1){
lines[i]+=";";
}
}
}
//log(lines[i]);
}
result = lines.join(' ');
//去除头尾{}
result = result.substring(2,result.length-1);
//收缩[]、{}、()
result = Compression.Shrink(result,"[","]",' ');
result = Compression.Shrink(result,"{","}",' ');
result = Compression.Shrink(result,"(",")",' ');
//去除多余代码段(非定义),去除var、function关键字
//合并跨行代码段
lines = result.split(";");
/*
for (var i=0,len = lines.length;i<len ; ++i)
{
log(lines[i]);
}
*/
for (var i=0,len = lines.length;i<len ; ++i)
{
var str = lines[i];
//log(str);
if (str.indexOf(" var ") === str.indexOf(" function ")){//-1
lines[i] = "";//清空
}else{//去除关键字,压缩空格
lines[i] = Compression.Trim(str.replace(" var ","").replace(" function ",""));
}
//log(lines[i]);
}
//最后一次收缩
//过滤无关字符以及关键字
lines = lines.join().split(',');
for (var i=0,len = lines.length;i<len ; ++i)
{
var str = lines[i],
em = str.indexOf(' ') ;
//log(str);
if (em!== -1){
lines[i] = str.substring(0, em);
}
}
///压缩代码
result = Compression.ArrayCompact(lines)//.join();
return Compression.ArrayUnique(result);
}
Compression.Trim = function(str) {
whitespace = ' \n\r\t\f\x0b\xa0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000';
for (var i = 0,len = str.length; i < len; i++) {
if (whitespace.indexOf(str.charAt(i)) === -1) {
str = str.substring(i);
break;
}
}
for (i = str.length - 1; i >= 0; i--) {
if (whitespace.indexOf(str.charAt(i)) === -1) {
str = str.substring(0, i + 1);
break;
}
}
return whitespace.indexOf(str.charAt(0)) === -1 ? str : '';
}
Compression.Shrink = function(str,first,last,replaceChar,justOne){
last = last||first;
replaceChar = replaceChar||'';
var begin = str.indexOf(first);
for (var i=begin,len = str.length,end=0;i<len ; ++i)
{
if (str.charAt(i)===first){
end++;
}else if (str.charAt(i)===last){
if(!--end){
str = str.substring(0,begin)+replaceChar+str.substring(1+i);
if (justOne){
return str;
}
len = str.length;
if((i = begin = str.indexOf(first))===-1)
{
break;
}else{
i--;
continue;
}
}
}
}
return str;
}
Compression.ArrayUnique = function(arr){
"use strict";
var arrStr = '.'+arr.join('.')+'.',res = [];
for (var i=0,j=0,len = arr.length;i<len ; ++i)
{
var item = arr[i];
arrStr = arrStr.replace(item,'');
if ( arrStr.indexOf('.'+item+'.') === -1 ){//Only one
res[j++] = item;
}
}
return res;
}
Compression.ArrayCompact = function(arr){
"use strict";
var res = [];
for (var i=0,j=0,len = arr.length;i<len ; ++i)
{
if (arr[i]){
res[j++] = arr[i];
}
}
return res;
}
;
var namespace = {
init:function(foo){
"use strict";
var N = {
run:this.run,
id: (++this.$$id)||(this.$$id = 0),
arguments : "",
packageFoo:this.packageFoo,
code:[],
out:function(Compression){
if (Compression){
return this.code.join('').split('\r\n').join('').replace(reg.MultiLineCComments,"")
.replace(reg.SingleLineCComments,"")
.replace(reg.Chars," $1 ")//格式化字符串
.replace((new RegExp(";[; ]+",'g')) ,";" )
.replace(reg.Empty," ");
}
return this.code.join('\n');
}
};
//log (this);
( namespace['__item__']&&(namespace['__item__'][N.id] = N) )||(namespace.__item__ = [N]);
//
if (foo){
return N.run(foo);
}else{
return N;
}
},
shrinkFoo : function(foo){
"use strict";
var code = Compression.Shrink( foo.toString().replace("function",""),'(',')','',true).replace("{",'');
for (var i=code.length-1,len = 0;i>=len ; --i)
{
if (code.charAt(i) === '}' ){
code = code.substring(0,i);
break;
}
}
return code;
},
packageCode : function(code){
"use strict";
return "try{"+ code +"}catch(e){console.log(e)};";
},
run:function(foo){//call by init-N
//log(this.id);
if (foo){
var newArgu = Compression.Trim( Compression(foo).join() );
if (newArgu){
if ( this.arguments ){
this.arguments +=',' + newArgu
}else{
this.arguments = newArgu;
}
}
//log(this.code.length);
var code = this.code[this.code.length] = namespace.shrinkFoo(foo) ;
eval( namespace.packageCode(code) );
var self = this;
eval("var returnFoo = function(){return function(foo){\n (function("+self.arguments+")"+Compression.Shrink( self.run.toString().replace("function",""),'(',')','',true)+").call(self, "+self.arguments +");return self;\n};}");
//log(returnFoo);
self.run = returnFoo();
return self;
}
log("should get one function");
}
//
}
//测试实现
var N = namespace.init()
N.run(function(s,z){
var a ="I'm a.",b="bbC";
var c = {a:"I'm c'a."};
log(a);
function x(){
log(a);
}
})
N.run(function(){
log(c.a+"in another place.");
x();
})
N.run(function(){
var obj= {
arr:[1,2,3,4]
}
})
;
log( N.out(true) )
//for CMD
//exports.namespace = namespace;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment