内容基本上来自于:《you dont know javascript》中卷 第4章 类型与文法
[] + {} // "[object Object]"
{} + [] // 0
先看第一个表达式,[ ] + { }
, 因为[]
会被强制转换为""
, 然后+
运算符 链接一个{ }
, { }
强制转换为字符串就是"[object Object]"
。 最终结果就是后者。
在看第二个表达式, 表达式第一个就是{ }
,这时候编译器只会把这个{ }
当作一个空代码块。【es6之前还没有块级作用,只有函数作用域和全局作用域,可以就理解为全局作用域下面一个多余的{ }
符号而已】,{ } + [ ]
就可以当作是+ [ ]
, 而 + [ ]
是强制将[ ]
转换为number ,转换的过程是 + [ ]
--> +""
-->0
最终的结果就是0。
好,我们举几个例子吧。
{}var a = 5;
{} console.log(a);
{var b = 6;}
console.log(b)
{var c = 7;}console.log(c);
这些语句都能在chrome控制台正确的运行。
可能你的疑问来了,比如在控制台里面输入{ name: “kevin” },也是能正常运行的,并且打印了这个对象。因为这时候它是一个表达式语句,就和在控制台输入5的时候是一样的,这时候chrome控制台打印的是定义的这个值。
但是我们这样输入,加一个分号 { name: “kevin” }; 你看控制台发生了什么变化,打印了"kevin", 因为这个语句的意思是,给字符串"kevin"打一个标签!! wtf ,的确是这样的。 如果不好理解的话 我们将字符串换成一个函数。
我们先定义了一个函数function bar(){}
, 然后给他打标签
{ barTag: bar };
就等于 barTag: bar
就等于 barTag: bar;
, 为什么{barTag: bar};
有这个分号,在chrome控制台里面,不加分号他就会被解析成一个对象。如果在html文件的script标签里面,加或者不加是一样的,都是打标签。
但是标签不是是字符串,就是说不可以这样 "barTag":bar
这里的打标签和for循环打标签类似:
foo: for (var i = 0; i < 4; i++) {
for (let j = 0; j < 4; j++) {
if (i * j >=3 ) {
console.log('stopping', i, j)
break foo
}
console.log(i, j)
}
}
然鹅我们也可以给代码块打标签:
function foo() {
bar: {
console.log('hello')
break bar
console.log('never runs')
}
console.log('world')
}
function bar() {}
{func: bar} // chrome 控制台打印的是什么
{func: bar}; // 这个呢?
看上面两个,一个打印的对象,一个是函数!第二个就是函数,func就是函数bar的标签。
我们也可以强制让{}+[]
的结果变成了0, 加一个括号即可。({}+[])
,只要不在一个语句的头部检测到{}
或者 ;{}
这种形式,那么它就不是一个代码块。(可能还有其他形式)。
但是我们执行console.log({}+[])
和console.log([]+{})
,结果是一样的,因为{}没有一个语句或者表达式的头部。
上面的所有实验是在chrome 控制台下的结果。
你也可以在html的script标签里面做一些实验。