这段神奇的JavaScript代码是如何工作的?

66

这是一小段JavaScript代码,它会弹出"Hello world"的提示框:

゚ω゚ノ=/`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/questions/23975/obfuscation-challenge/24041#24041

它是如何工作的?我甚至看不到那个alert


13
第三条评论中有一个简短的解释,位于http://codegolf.stackexchange.com/questions/307/obfuscated-hello-world/3946#3946 - NPE
1
@NPE 是的,我看到了那个,但作者只是给了一个小提示。我仍然不知道它是如何工作的... - Tony Dinh
1
你链接的答案提供了一个指向答案原始来源的进一步链接。在接下来的评论中,给出了一个解释 - 它使用了RegEx和其他工具。顺便说一句,你的“好看版本”是不正确的 - 我在最后一行发现了='\"';,可能还有其他错误。 - enhzflep
1
一些提示:在JavaScript中,您可以使用几乎所有Unicode字符作为变量名。第二件事是第一个变量似乎是一个正则表达式,它执行一些替换操作,但我不理解整个代码。 - rekire
9
我找到了这个工具。http://utf-8.jp/public/aaencode.html - Royi Namir
此外,关于JavaScript标识符的主题,还可以参考Mathias Bynens的这篇精彩文章 - poke
3个回答

113

在深入研究代码之前,您需要知道自从JavaScript 1.5以来,标识符不仅可以包含ASCII字符,还可以包含Unicode字符。

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

a = /`m´)ノ~┻━┻/['_'];
o = b = _ = 3;
c = d = b-b;
e = d = o^_^o/o^_^o;
e = {
  d: '_',
  a: ((a==3)+'_')[d],
  h: (a+'_')[o^_^o-d],
  i: ((b==3)+'_')[b]
};
e[d]   = ((a==3)+'_')[c^_^o];
e['c'] = (e+'_')[b+b-d];
e['o'] = (e+'_')[d];
f      = e['c']+e['o']+(a+'_')[d]+((a==3)+'_')[b]+(e+'_')[b+b]+((b==3)+'_')[d]+((b==3)+'_')[b-d]+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^_^o-d]+((b==3)+'_')[d]+(a+'_')[d];
b      += d;
e[g]   = '\\';
e.j    = (e+b)[o^_^o-d];
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 将整数 3 分配给变量 ob_
  • c = d = b-b 将整数 0 分配给变量 cd
  • e = d = o^_^o/o^_^o 将整数 1 分配给变量 edo^_^o计算结果为3异或3异或3,得到3)
  • e = { d: '_', a: ((a==3)+'_')[d], h: (a+'_')[o^_^o-d], i: ((b==3)+'_')[b] } 将对象 { d: '_', a: 'a', h: 'd', i: 'e' } 分配给变量 e
  • e[d] = ((a==3)+'_')[c^_^o] 将字符串 'f' 分配给变量 e[1]
  • e['c'] = (e+'_')[b+b-d] 将字符串 'c' 分配给变量 e['c']
  • e['o'] = (e+'_')[d] 将字符串 'o' 分配给变量 e['o']
这只是设置阶段,以下变量已设置:
a = undefined
b = 3
c = 0
d = 1
e = {
    1: "f",
    a: "a",
    c: "c",
    d: "_",
    h: "d",
    i: "e",
    o: "o"
}

下一个语句是第一个构造某些东西的语句:
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)+'_')[b-d] +  // => "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 函数很特殊,因为它可以通过参数传递函数体代码来动态构建函数:

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

我会跳过接下来的几个语句,直接写出变量和值的结果:

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))('_')

长表达式构建了以下字符串:
return"\141\154\145\162\164\50\42\110\145\154\154\157\40\127\157\162\154\144\42\51"

转义后的字符串将被计算为:
alert("Hello World")

这个return代码被传递给Function,它会创建一个匿名函数,如下所示:

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执行此函数,返回结果字符串:

alert("Hello World")

然后将其再次传递给Function,它将创建一个新的匿名函数:

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

最后,这个函数也会使用'_'作为参数被调用。

2
谢谢,等待这个答案。写这篇文章的人非常聪明,我从这个答案和他的博客中学到了很多东西。 - Tony Dinh
1
“JavaScript 1.5”并不是真正存在的东西。如果你想引用一个规范,你应该查看ES3或ES5规范。顺便说一句,回答很棒。 - Benjamin Gruenbaum

16

这里有很多东西。变量周围的括号没有实际意义。

基本上,他构造了这个字符串:

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()将字符串中的反斜杠解释为转义字符。因此第一次调用是解码,第二次调用是执行。

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

这是相同的代码,格式更好,并且使用了“正常”的变量名称;

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)
)('_');

゚ω゚ノ 怎么变成 var 的? - Royi Namir
2
@RoyiNamir 不是这样的。我已经随意将其重命名为 var1。它是工作中的 JavaScript,而不是“最佳实践”JavaScript。你在这里找不到任何 var - sabof
有没有一个在线工具可以做到这一点?(不仅仅是编码,我的意思是那个 ^ 符号) - Royi Namir
@RoyiNamir 解混淆?我不知道,我是通过搜索和替换来完成的,还定期检查它是否仍然有效。 - sabof
不,我指的是混淆。我知道常规工具,但它们无法产生这种混淆。 - Royi Namir
@RoyiNamir 我也不知道。 - sabof

10

让我解释一下关键步骤:

该代码创建了一个名为Д的对象,然后添加了一个名为'_'的属性,其值是神奇的JavaScriptFunction构造函数。在JavaScript中,您可以通过将字符串传递给Function构造函数来执行任何字符串作为代码。

(゚Д゚)['_']如何包含Function构造函数?这是通过以下代码巧妙地实现的:

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

在这里,o和_都设置为3。所以o^_^o返回3。显然作者本可以只使用o,因为o^_^o返回相同的值,但我想他对混淆有好的品味:)。所以上面的表达式现在变成了(3)[゚o゚][゚o゚]

方括号中的゚o゚的值设为字符串"constructor",该字符串是在前一个语句中通过连接构建的。它使用了一种非常巧妙的方法来构建字符串"constructor",即从内置JavaScript字符串(如"object"、"true"、"false"和"undefined")中抽取单个字符,这些字符串是从转换为字符串的JavaScript表达式生成的。显然,作者无法从这些内置字符串中找到要提取的字符"c",因此不得不明确地编写该字符。请注意,方括号中的字符是Unicode字符,而不是圆括号中使用的简单o,尽管两者看起来非常相似。当您执行(3)("constructor")时,它将返回数字构造函数。Number构造函数的构造函数是Function构造函数。因此,通过执行(3)("constructor")("constructor"),您可以获得Function构造函数,现在您终于可以传递任意字符串来执行它了。

最后一行构建了字符串"alert(\"Hello World\")"并将其传递给Function构造函数以执行。

问题是如何获取字符串"alert(\"Hello World\")"而不输入实际的字母?聪明的技巧是使用\xxx,其中xxx是八进制数,并转换为字符。要获取此字符串,您需要的数字是0、1、2、3、4、5、6、7和8。但实际上您不需要全部这些数字,而是可以通过三个数字0、1和4进行简单算术运算来产生它们。因此,例如,要在"alert"中生成字符'a',您需要ASCII十进制97或八进制141,即\141。如果您只在上述对象的某个属性中存储了0、1和4,则可以将它们连接起来生成'a'。通过这种方式,即使您只有存储在Д对象的某些属性中的0、1和4,也可以生成任何字符串。聪明吧?你打赌!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接