在JavaScript中~[]构造是如何工作的?

在JavaScript中~[]构造是如何工作的?,javascript,brackets,tilde,Javascript,Brackets,Tilde,我遇到了一个无法解释的JavaScript代码。 例如: +[]==0 -[]==0 ~[]==-1 ~-~[]==-2 ~-~-~-~[]==-5 ~-~-~-~[]+~[]==-6 ~+~[]==0 ~+~+~[]==-1 ~+~+~+~[]==0 您能解释一下这些表达式的逻辑吗?[]是一个空数组对象,因此: +[]:强制空数组为正整数,也称为0,即===到0 -[]:强制空数组为负整数,也称为0,即===到0 ~[]:按位非空数组,其计算结果为-1,即===到-1 ~-~[]:按位NO

我遇到了一个无法解释的JavaScript代码。 例如:

  • +[]==0
  • -[]==0
  • ~[]==-1
  • ~-~[]==-2
  • ~-~-~-~[]==-5
  • ~-~-~-~[]+~[]==-6
  • ~+~[]==0
  • ~+~+~[]==-1
  • ~+~+~+~[]==0

您能解释一下这些表达式的逻辑吗?

[]
是一个空数组对象,因此:

+[]:强制空数组为正整数,也称为0,即===到0
-[]:强制空数组为负整数,也称为0,即===到0
~[]:按位非空数组,其计算结果为-1,即===到-1
~-~[]:按位NOT的求反NOTted空数组:
~-(-1)->~1->-2


等等。

当您对任何内容使用
+
-
运算符时,它会调用其上的
数字
Number([])
返回
0
,因此您可以得到前两个答案

~
运算符不是按位的。基本上,它将一个数字中的所有位反转,从而将
0
更改为
-1
。更多关于位运算符的信息


其余的只是这些案例的组合。你几乎可以把这些东西组合成你想要的任何数字。

我相信,如果我错了,请纠正我,但是添加到数组(例如,向数组中添加值而不是向数组中添加值)会将其转换为数字。其余的只是使用基本+,-运算符(波浪号(~)是一个按位NOT)修改数字,然后修改一个方程

So [] == array ([]);
[] + 1 == number (0);
+[]===0 (true)
我会尽力而为:

[]==0
当然是错误的,因为
[]
并不完全等于0。但是,
[]==0
为真,因为存在隐式强制转换

+
-[]
之所以有效,是因为加号或减号将
[]
转换为实数

~0
(0的位逆)是-1。因此,
~[]=-1
起作用


其他方法只是通过多次减去或加-1来工作。

我将尝试描述为什么会得到这个结果,而不是重复您在问题中演示的结果

解释

仅以第一个示例为例(因为其他示例将执行类似的操作),我们可以按照规范来查看发生了什么

从中,我们可以看到发生了
ToNumber
转换

返回ToNumber(GetValue(expr))

从中我们可以看到,如果给定一个对象(如数组),则会进行
ToPrimitive
转换,然后再次尝试
ToNumber

对象

应用以下步骤:

  • 让PrimitValue为TopPrimitive(输入参数、提示号)
  • 返回tonNumber(primValue)
  • 从中,如果
    ToPrimitive
    获取一个对象,我们可以看到它的
    [[DefaultValue]]]
    被获取:

    对象

    返回对象的默认值。通过调用对象的[[DefaultValue]]内部方法并传递可选提示PreferredType,可以检索对象的默认值。[[DefaultValue]]内部方法的行为由本规范为8.12.8中的所有本机ECMAScript对象定义

    从中,最终将对数组调用并返回
    toString()
    。如上所述,此字符串被发送到递归的
    ToNumber

    那么当对字符串进行
    ToNumber
    转换时会发生什么呢?嗯,这是在中描述的,有点长。更简单的方法是直接进行转换,看看会发生什么:

    Number("");     // result is 0 on an empty string
    Number("    "); // result is 0 on a string with only whitespace
    Number("123");  // result is 123 on a numeric string
    Number(" 123 ");// result is 123 on a numeric string with leading & trailing spaces
    Number("abc");  // result is NaN (not a number) on non-numeric strings
    
    所以问题是,我们从数组中得到什么字符串。同样,这很容易进行简单的测试

    [].toString();  // result is "" (empty string)
    
    由于结果是一个空字符串,并且空字符串的
    ToNumber
    转换是
    0
    ,如上图所示,这意味着我们正在比较
    0==0

    这与我们所做的一样:

    Number( [].toString() ) === 0; // true
    
    或者更详细地说:

    var x = [];
    x = x.toString();  // ""
    x = Number( x );   // 0
    x === 0;  // true
    

    更多
    toString
    结果。

    显示更多的<代码> toStase数组的转换,请考虑以下内容:

    [1].toString();            // "1"
    [1,2,3].toString();        // "1,2,3"
    ["a",1,"b",2].toString();  // "a,1,b,2"
    
    因此,要对上述数组进行
    ToNumber
    转换,第一个数组将给出一个数字,最后两个数组将得到
    NaN

    Number([1]);            // 1
    Number([1,2,3]);        // NaN
    Number(["a",1,"b",2]);  // NaN
    

    一些证据

    为了进一步证明此
    toString()
    转换发生在
    ToNumber
    转换之前,我们实际上可以修改
    Array.prototype.toString
    以提供不同的结果,任何
    ToNumber
    转换都将使用修改后的结果

    Array.prototype.toString = function() {
        var n = 0;
        for( var i = 0; i < this.length; i++ ) {
            n += this[i];
        }
        return n;
    };
    

    所以现在你可以看到我们的数组的
    ToNumber
    转换以前会产生
    NaN
    ,现在会产生数组中项目的总和。

    如果我遇到这样的代码,我想我会翻桌子。答案是:
    +[NaN]==!!!!0&&+[{}]+~~[[]]-[]
    如果我在任何代码库中看到这一点,我会要求原始开发人员重写它。这是非常糟糕的练习!!!这些是JavaScript的宝剑。使用它们来获得最大的公正。事实上,它将其转换为一个字符串,而不是一个数字
    [1]+1=“11”
    所以
    +[]=0
    因为这就像做
    +”
    应该是:
    ~1->-2
    在最后一个字符串-1
    +[]:强制空数组为正整数,也就是0,这并不能解释为什么会发生这种情况。它只是重申了结果。显然,如果
    +[]==0
    ,则
    +[]
    必须已转换为
    0
    。这个问题要求解释逻辑,明白了。我错过了
    []
    0
    部分的演员阵容。
    Number([1,2,3]);   // 6
    +[1,2,3];          // 6