这个神奇的Javascript是如何工作的?

这是一个小的JavaScript提醒“你好世界”:

゚ω゚ノ=/`m´)ノ~┻━┻//*´∇`*/['_'];o=(゚ー゚)=_=3;c=(゚Θ゚)=(゚ー゚)-(゚ー゚);(゚Д゚)=(゚Θ゚)=(o^_^o)/(o^_^o);(゚Д゚)={゚Θ゚:'_',゚ω゚ノ:((゚ω゚ノ==3)+'_')[゚Θ゚],゚ー゚ノ:(゚ω゚ノ+'_')[o^_^o-(゚Θ゚)],゚Д゚ノ:((゚ー゚==3)+'_')[゚ー゚]};(゚Д゚)[゚Θ゚]=((゚ω゚ノ==3)+'_')[c^_^o];(゚Д゚)['c']=((゚Д゚)+'_')[(゚ー゚)+(゚ー゚)-(゚Θ゚)];(゚Д゚)['o']=((゚Д゚)+'_')[゚Θ゚];(゚o゚)=(゚Д゚)['c']+(゚Д゚)['o']+(゚ω゚ノ+'_')[゚Θ゚]+((゚ω゚ノ==3)+'_')[゚ー゚]+((゚Д゚)+'_')[(゚ー゚)+(゚ー゚)]+((゚ー゚==3)+'_')[゚Θ゚]+((゚ー゚==3)+'_')[(゚ー゚)-(゚Θ゚)]+(゚Д゚)['c']+((゚Д゚)+'_')[(゚ー゚)+(゚ー゚)]+(゚Д゚)['o']+((゚ー゚==3)+'_')[゚Θ゚];(゚Д゚)['_']=(o^_^o)[゚o゚][゚o゚];(゚ε゚)=((゚ー゚==3)+'_')[゚Θ゚]+(゚Д゚).゚Д゚ノ+((゚Д゚)+'_')[(゚ー゚)+(゚ー゚)]+((゚ー゚==3)+'_')[o^_^o-゚Θ゚]+((゚ー゚==3)+'_')[゚Θ゚]+(゚ω゚ノ+'_')[゚Θ゚];(゚ー゚)+=(゚Θ゚);(゚Д゚)[゚ε゚]='\\';(゚Д゚).゚Θ゚ノ=(゚Д゚+゚ー゚)[o^_^o-(゚Θ゚)];(o゚ー゚o)=(゚ω゚ノ+'_')[c^_^o];(゚Д゚)[゚o゚]='\"';(゚Д゚)['_']((゚Д゚)['_'](゚ε゚+(゚Д゚)[゚o゚]+(゚Д゚)[゚ε゚]+(゚Θ゚)+(゚ー゚)+(゚Θ゚)+(゚Д゚)[゚ε゚]+(゚Θ゚)+((゚ー゚)+(゚Θ゚))+(゚ー゚)+(゚Д゚)[゚ε゚]+(゚Θ゚)+(゚ー゚)+((゚ー゚)+(゚Θ゚))+(゚Д゚)[゚ε゚]+(゚Θ゚)+((o^_^o)+(o^_^o))+((o^_^o)-(゚Θ゚))+(゚Д゚)[゚ε゚]+(゚Θ゚)+((o^_^o)+(o^_^o))+(゚ー゚)+(゚Д゚)[゚ε゚]+((゚ー゚)+(゚Θ゚))+(c^_^o)+(゚Д゚)[゚ε゚]+(゚ー゚)+((o^_^o)-(゚Θ゚))+(゚Д゚)[゚ε゚]+(゚Θ゚)+(゚Θ゚)+(c^_^o)+(゚Д゚)[゚ε゚]+(゚Θ゚)+(゚ー゚)+((゚ー゚)+(゚Θ゚))+(゚Д゚)[゚ε゚]+(゚Θ゚)+((゚ー゚)+(゚Θ゚))+(゚ー゚)+(゚Д゚)[゚ε゚]+(゚Θ゚)+((゚ー゚)+(゚Θ゚))+(゚ー゚)+(゚Д゚)[゚ε゚]+(゚Θ゚)+((゚ー゚)+(゚Θ゚))+((゚ー゚)+(o^_^o))+(゚Д゚)[゚ε゚]+(゚ー゚)+(c^_^o)+(゚Д゚)[゚ε゚]+(゚Θ゚)+((o^_^o)-(゚Θ゚))+((゚ー゚)+(o^_^o))+(゚Д゚)[゚ε゚]+(゚Θ゚)+((゚ー゚)+(゚Θ゚))+((゚ー゚)+(o^_^o))+(゚Д゚)[゚ε゚]+(゚Θ゚)+((o^_^o)+(o^_^o))+((o^_^o)-(゚Θ゚))+(゚Д゚)[゚ε゚]+(゚Θ゚)+((゚ー゚)+(゚Θ゚))+(゚ー゚)+(゚Д゚)[゚ε゚]+(゚Θ゚)+(゚ー゚)+(゚ー゚)+(゚Д゚)[゚ε゚]+(゚ー゚)+((o^_^o)-(゚Θ゚))+(゚Д゚)[゚ε゚]+((゚ー゚)+(゚Θ゚))+(゚Θ゚)+(゚Д゚)[゚o゚])(゚Θ゚))('_'); 

一个好看的版本:

 ゚ω゚ノ = /`m´)ノ~┻━┻//*´∇`*/['_']; o = (゚ー゚) = _ = 3; c = (゚Θ゚) = (゚ー゚) - (゚ー゚); (゚Д゚) = (゚Θ゚) = (o^_^o)/(o^_^o); (゚Д゚) = {゚Θ゚: '_',゚ω゚ノ: ((゚ω゚ノ==3)+'_')[゚Θ゚],゚ー゚ノ: (゚ω゚ノ+'_')[o^_^o-(゚Θ゚)],゚Д゚ノ: ((゚ー゚==3)+'_')[゚ー゚] }; (゚Д゚)[゚Θ゚] = ((゚ω゚ノ==3)+'_')[c^_^o]; (゚Д゚)['c'] = ((゚Д゚)+'_')[(゚ー゚)+(゚ー゚)-(゚Θ゚)]; (゚Д゚)['o'] = ((゚Д゚)+'_')[゚Θ゚]; (゚o゚)=(゚Д゚)['c'] + (゚Д゚)['o'] + (゚ω゚ノ + '_')[゚Θ゚] + ((゚ω゚ノ==3) + '_')[゚ー゚] + ((゚Д゚) + '_')[(゚ー゚) + (゚ー゚)] + ((゚ー゚==3) + '_')[゚Θ゚] + ((゚ー゚==3) + '_')[(゚ー゚) - (゚Θ゚)] + (゚Д゚)['c'] + ((゚Д゚) + '_')[(゚ー゚) + (゚ー゚)] + (゚Д゚)['o'] + ((゚ー゚==3) + '_')[゚Θ゚]; (゚Д゚)['_'] = (o^_^o)[゚o゚][゚o゚]; (゚ε゚) = ((゚ー゚==3) + '_')[゚Θ゚] + (゚Д゚).゚Д゚ノ + ((゚Д゚) + '_')[(゚ー゚) + (゚ー゚)] + ((゚ー゚==3) + '_')[o^_^o-゚Θ゚] + ((゚ー゚==3) + '_')[゚Θ゚] + (゚ω゚ノ+'_')[゚Θ゚]; (゚ー゚) += (゚Θ゚); (゚Д゚)[゚ε゚] = '\\'; (゚Д゚).゚Θ゚ノ = (゚Д゚+゚ー゚)[o^_^o-(゚Θ゚)]; (o゚ー゚o) = (゚ω゚ノ+'_')[c^_^o]; (゚Д゚)[゚o゚] = '\"'; (゚Д゚)['_']((゚Д゚)['_'](゚ε゚+(゚Д゚)[゚o゚]+(゚Д゚)[゚ε゚]+(゚Θ゚)+(゚ー゚)+(゚Θ゚)+(゚Д゚)[゚ε゚]+(゚Θ゚)+((゚ー゚)+(゚Θ゚))+(゚ー゚)+(゚Д゚)[゚ε゚]+(゚Θ゚)+(゚ー゚)+((゚ー゚)+(゚Θ゚))+(゚Д゚)[゚ε゚]+(゚Θ゚)+((o^_^o)+(o^_^o))+((o^_^o)-(゚Θ゚))+(゚Д゚)[゚ε゚]+(゚Θ゚)+((o^_^o)+(o^_^o))+(゚ー゚)+(゚Д゚)[゚ε゚]+((゚ー゚)+(゚Θ゚))+(c^_^o)+(゚Д゚)[゚ε゚]+(゚ー゚)+((o^_^o)-(゚Θ゚))+(゚Д゚)[゚ε゚]+(゚Θ゚)+(゚Θ゚)+(c^_^o)+(゚Д゚)[゚ε゚]+(゚Θ゚)+(゚ー゚)+((゚ー゚)+(゚Θ゚))+(゚Д゚)[゚ε゚]+(゚Θ゚)+((゚ー゚)+(゚Θ゚))+(゚ー゚)+(゚Д゚)[゚ε゚]+(゚Θ゚)+((゚ー゚)+(゚Θ゚))+(゚ー゚)+(゚Д゚)[゚ε゚]+(゚Θ゚)+((゚ー゚)+(゚Θ゚))+((゚ー゚)+(o^_^o))+(゚Д゚)[゚ε゚]+(゚ー゚)+(c^_^o)+(゚Д゚)[゚ε゚]+(゚Θ゚)+((o^_^o)-(゚Θ゚))+((゚ー゚)+(o^_^o))+(゚Д゚)[゚ε゚]+(゚Θ゚)+((゚ー゚)+(゚Θ゚))+((゚ー゚)+(o^_^o))+(゚Д゚)[゚ε゚]+(゚Θ゚)+((o^_^o)+(o^_^o))+((o^_^o)-(゚Θ゚))+(゚Д゚)[゚ε゚]+(゚Θ゚)+((゚ー゚)+(゚Θ゚))+(゚ー゚)+(゚Д゚)[゚ε゚]+(゚Θ゚)+(゚ー゚)+(゚ー゚)+(゚Д゚)[゚ε゚]+(゚ー゚)+((o^_^o)-(゚Θ゚))+(゚Д゚)[゚ε゚]+((゚ー゚)+(゚Θ゚))+(゚Θ゚)+(゚Д゚)[゚o゚])(゚Θ゚))('_'); 

的jsfiddle

采取从这里: https : //codegolf.stackexchange.com/a/24041/17049

任何人都知道它是如何工作的? 我甚至没有看到该代码中的alert

在仔细观察代码之前,您必须知道,由于JavaScript 1.5 标识符不仅允许包含ASCII字符,而且还允许包含Unicode字符。

在这种情况下,许多有趣的序列只是标识符。 通过简单的标识符交换这些标识符,并删除不必要的注释和括号后,代码如下所示:

 a = /`m´)ノ~┻━┻/['_']; o = b = _ = 3; c = d = bb; e = d = o^_^o/o^_^o; e = { d: '_', a: ((a==3)+'_')[d], h: (a+'_')[o^_^od], i: ((b==3)+'_')[b] }; e[d] = ((a==3)+'_')[c^_^o]; e['c'] = (e+'_')[b+bd]; e['o'] = (e+'_')[d]; f = e['c']+e['o']+(a+'_')[d]+((a==3)+'_')[b]+(e+'_')[b+b]+((b==3)+'_')[d]+((b==3)+'_')[bd]+e['c']+(e+'_')[b+b]+e['o']+((b==3)+'_')[d]; e['_'] = (o^_^o)[f][f]; g = ((b==3)+'_')[d]+e.i+(e+'_')[b+b]+((b==3)+'_')[o^_^od]+((b==3)+'_')[d]+(a+'_')[d]; b += d; e[g] = '\\'; ej = (e+b)[o^_^od]; obo = (a+'_')[c^_^o]; e[f] = '\"'; e['_'](e['_'](g+e[f]+e[g]+d+b+d+e[g]+d+(b+d)+b+e[g]+d+b+(b+d)+e[g]+d+((o^_^o)+(o^_^o))+((o^_^o)-d)+e[g]+d+((o^_^o)+(o^_^o))+b+e[g]+(b+d)+(c^_^o)+e[g]+b+((o^_^o)-d)+e[g]+d+d+(c^_^o)+e[g]+d+b+(b+d)+e[g]+d+(b+d)+b+e[g]+d+(b+d)+b+e[g]+d+(b+d)+(b+(o^_^o))+e[g]+b+(c^_^o)+e[g]+d+((o^_^o)-d)+(b+(o^_^o))+e[g]+d+(b+d)+(b+(o^_^o))+e[g]+d+((o^_^o)+(o^_^o))+((o^_^o)-d)+e[g]+d+(b+d)+b+e[g]+d+b+b+e[g]+b+((o^_^o)-d)+e[g]+(b+d)+d+e[f])(d))('_'); 

现在我们可以一次评估每条语句:

  • a = /`m´)ノ~┻━┻/['_']计算结果为a = undefined
  • o = b = _ = 3分配ob_整数3
  • c = d = bbcd分配给整数0
  • e = d = o^_^o/o^_^o赋予ed整数1o^_^o值为3 XOR 3 XOR 3,得出3)
  • e = { d: '_', a: ((a==3)+'_')[d], h: (a+'_')[o^_^od], i: ((b==3)+'_')[b] }指定对象{ d: '_', a: 'a', h: 'd', i: 'e' }
  • e[d] = ((a==3)+'_')[c^_^o]赋值e[1]string'f'
  • e['c'] = (e+'_')[b+bd]e['c']赋值给string'c'
  • e['o'] = (e+'_')[d]赋值e['o']string'o'

这只是设置和以下variables设置:

 a = undefined b = 3 c = 0 d = 1 e = { 1: "f", a: "a", c: "c", d: "_", h: "d", i: "e", o: "o" } 

下一个陈述是第一个构build的东西:

 f = e['c'] + // => "c" e['o'] + // => "o" (a+'_')[d] + // => "undefined_"[1] = "n" ((a==3)+'_')[b] + // => "false_"[3] = "s" (e+'_')[b+b] + // => "object_"[6] = "t" ((b==3)+'_')[d] + // => "true_"[1] = "r" ((b==3)+'_')[bd] + // => "true_"[2] = "s" e['c'] + // => "c" (e+'_')[b+b] + // => "object_"[6] = "t" e['o'] + // => "o" ((b==3)+'_')[d]; // => "true"[1] = "r" 

所以f = "constructor" 。 在下一个语句中,这个"constructor"用于检索一个函数:

 e['_'] = (o^_^o)[f][f] 

这相当于(3).constructor.constructor ,它产生函数Function ,所以:

 e['_'] = Function 

这个Function函数是非常特殊的,可以通过parameter passing函数体代码来dynamic地构造函数:

 f = Function("alert(1)") // equivalent to f = function() { alert(1) } 

我将跳过接下来的几条语句,只写出结果variables和值:

 a = undefined b = 4 c = 0 d = 1 e = { 1: "f", _: Function, a: "a", c: "c", constructor: "\"", d: "_", h: "d", i: "e", j: "b", o: "o", return: "\\" } f = "constructor" obo = "u" 

最后的声明做最后的工作:

 e['_'](e['_'](g+e[f]+e[g]+d+b+d+e[g]+d+(b+d)+b+e[g]+d+b+(b+d)+e[g]+d+((o^_^o)+(o^_^o))+((o^_^o)-d)+e[g]+d+((o^_^o)+(o^_^o))+b+e[g]+(b+d)+(c^_^o)+e[g]+b+((o^_^o)-d)+e[g]+d+d+(c^_^o)+e[g]+d+b+(b+d)+e[g]+d+(b+d)+b+e[g]+d+(b+d)+b+e[g]+d+(b+d)+(b+(o^_^o))+e[g]+b+(c^_^o)+e[g]+d+((o^_^o)-d)+(b+(o^_^o))+e[g]+d+(b+d)+(b+(o^_^o))+e[g]+d+((o^_^o)+(o^_^o))+((o^_^o)-d)+e[g]+d+(b+d)+b+e[g]+d+b+b+e[g]+b+((o^_^o)-d)+e[g]+(b+d)+d+e[f])(d))('_'); 

这相当于:

 Function(Function( … )(1))('_') 

longexpression式生成以下string:

 return"\141\154\145\162\164\50\42\110\145\154\154\157\40\127\157\162\154\144\42\51" 

转义string评估:

 alert("Hello World") 

这个return码被传递给Function ,它创build一个匿名函数,如:

 function anonymous() { return"\141\154\145\162\164\50\42\110\145\154\154\157\40\127\157\162\154\144\42\51"; } 

我们知道,这相当于:

 function anonymous() { return"alert(\"Hello World\")"; } 

然后用1作为参数执行该函数,返回结果string:

 alert("Hello World") 

然后再传递给Function ,从而创build一个新的匿名函数:

 function anonymous() { alert("Hello World"); } 

最后,这个函数也是以'_'作为参数来调用的。

这里有很多东西。 variables周围的括号是不起作用的。

基本上他构造这个string:

 return"\141\154\145\162\164\50\42\110\145\154\154\157\40\127\157\162\154\144\42\51" 

这是一个逃脱版本

 return "alert(\"Hello World\")" 

最后这样做:

 Function(Function('return "alert(\\"Hello World\\")"')())() 

双重Function似乎是一个随心所欲的事情,但事实并非如此。 Function()将string中的反斜杠解释为转义字符。 所以第一个调用解码,第二个执行。

 Function("return '\\110\\145\\154\\154\\157'")() // => "Hello" 

这是相同的代码,更好的格式,并与“正常”的variables名称;

 var1=/`m´)ノ~┻━┻//*´∇`*/['_']; three=(threeThenFour)=_=3; c=(one)=(threeThenFour)-(threeThenFour); (anObject)=(one)=(three)/(three); (anObject)={ one:'_', var1:((var1==3)+'_')[one], var2ノ:(var1+'_')[three-(one)], var4ノ:((threeThenFour==3)+'_')[threeThenFour] }; (anObject)[one]=((var1==3)+'_')[c ^ _ ^ three]; (anObject)['c']=((anObject)+'_')[(threeThenFour)+(threeThenFour)-(one)]; (anObject)['three']=((anObject)+'_')[one]; (theConstructor)=(anObject)['c']+ (anObject)['three']+ (var1+'_')[one]+ ((var1==3)+'_')[threeThenFour]+ ((anObject)+'_')[(threeThenFour)+(threeThenFour)]+ ((threeThenFour==3)+'_')[one]+ ((threeThenFour==3)+'_')[(threeThenFour)-(one)]+ (anObject)['c']+ ((anObject)+'_')[(threeThenFour)+(threeThenFour)]+ (anObject)['three']+ ((threeThenFour==3)+'_')[one]; // theConstructor => "constructor" (anObject)['_']=(three)[theConstructor][theConstructor]; (theReturn)=((threeThenFour==3)+'_')[one]+ (anObject).var4ノ+ ((anObject)+'_')[(threeThenFour)+(threeThenFour)]+ ((threeThenFour==3)+'_')[three-one]+ ((threeThenFour==3)+'_')[one]+ (var1+'_')[one]; // theReturn => "return" (threeThenFour)+=(one); (anObject)[theReturn]='\\'; (anObject).var3ノ=(anObject+threeThenFour)[three-(one)]; (ovar2o)=(var1+'_')[c ^ _ ^ three]; (anObject)[theConstructor]='\"'; // (anObject)['_'] => Function (anObject)['_']( (anObject)['_'](theReturn+ (anObject)[theConstructor]+ (anObject)[theReturn]+ (one)+ (threeThenFour)+ (one)+ (anObject)[theReturn]+ (one)+ ((threeThenFour)+(one))+ (threeThenFour)+ (anObject)[theReturn]+ (one)+( threeThenFour)+ ((threeThenFour)+(one))+ (anObject)[theReturn]+ (one)+ ((three)+(three))+ ((three)-(one))+ (anObject)[theReturn]+ (one)+ ((three)+(three))+ (threeThenFour)+ (anObject)[theReturn]+ ((threeThenFour)+(one))+ (c ^ _ ^ three)+ (anObject)[theReturn]+ (threeThenFour)+((three)-(one))+ (anObject)[theReturn]+ (one)+(one)+ (c ^ _ ^ three)+ (anObject)[theReturn]+ (one)+ (threeThenFour)+ ((threeThenFour)+(one))+ (anObject)[theReturn]+ (one)+ ((threeThenFour)+(one))+ (threeThenFour)+ (anObject)[theReturn]+ (one)+ ((threeThenFour)+(one))+ (threeThenFour)+ (anObject)[theReturn]+ (one)+ ((threeThenFour)+(one))+ ((threeThenFour)+(three))+ (anObject)[theReturn]+ (threeThenFour)+ (c ^ _ ^ three)+ (anObject)[theReturn]+ (one)+ ((three)-(one))+ ((threeThenFour)+(three))+ (anObject)[theReturn]+ (one)+ ((threeThenFour)+(one))+ ((threeThenFour)+(three))+ (anObject)[theReturn]+ (one)+ ((three)+(three))+ ((three)-(one))+ (anObject)[theReturn]+ (one)+ ((threeThenFour)+(one))+ (threeThenFour)+ (anObject)[theReturn]+ (one)+ (threeThenFour)+ (threeThenFour)+ (anObject)[theReturn]+ (threeThenFour)+ ((three)-(one))+ (anObject)[theReturn]+ ((threeThenFour)+(one))+ (one)+ (anObject)[theConstructor] ) (one) )('_'); 

让我解释一下关键步骤:

该代码创build一个名为Д的对象,然后添加一个属性'_' ,该属性具有魔术JavaScript 函数构造函数的值。 在JavaScript中,您可以将任何string作为代码传递给Function构造函数。

(゚Д゚)['_']包含Function构造函数? 这是聪明的技术完成下面的行:

 (゚Д゚)['_'] = (o^_^o)[゚o゚][゚o゚]; 

这里o和_被设置为3.所以o^_^o返回到3.显然作者可能刚刚使用了o,因为o^_^o返回相同的值,但是我猜他对混淆有很好的感觉:)。 所以上面的expression式现在变成(3)[゚o゚][゚o゚]

方括号中的゚o゚ value的值被设置为在前面的语句中通过串联构build的string“构造函数”。 它通过从JavaScript转换为string的JavaScriptexpression式中生成的“object”,“true”,“false”和“undefined”等内置JavaScriptstring中删除单个字符来构buildstring“构造函数”。 显然作者找不到字符“c”从这些内置的string中删除,所以他必须明确地写出这个字符。 请注意,方括号中的字符是Unicode字符,而不是圆括号中使用的简单字符,虽然两者看起来非常相似。 当你做(3)("constructor")它返回数字构造函数 。 Number构造函数的构造函数是Function构造函数。 所以通过做(3)("constructor")("constructor")你得到函数的构造函数,现在你可以终于传递一个任意的string来执行它。

最后一行build立string"alert(\"Hello World\")"并将其传递给Function构造函数来执行。

问题是我们如何得到这个string"alert(\"Hello World\")"而不input实际的字母表? 巧妙的方法是使用\xxx其中xxx是八进制数,并转换为一个字符。 要得到这个string,你需要的数字是0,1,2,3,4,5,6,7和8.但是你实际上并不需要所有这些,你可以用三个数字0 ,1和4.例如,要在“alert”中产生字符'a' ”,则需要ASCII小数97或八进制141,即\141 。 如果只有0,1和4存储在上述对象的某个属性中,则可以连接它们以产生'a' 。 这样你可以生成任何string,即使你所有的都是0,1和4存储在Д对象的某些属性中。 聪明? 你打赌!

Interesting Posts