在javascript早期,有着不少明显的设计失误。这些设计失误导致了一些语法有着极为诡异的行为。在现在看来,这些语法在实际应用中是禁止被使用的。否则程序会被引入各种奇怪的行为,而且查找出错误的位置也相当耗时间。
这两个符号居然一言不合就做类型转换,导致''和0会被判成相等。因此永远使用不带类型转换的===
和!==
,或者使用Object.is
。
下面的语句返回什么?
function func() {
return
{
a: 1
};
}
如果你认为函数返回的是一个对象,那么你图样图森破。Javascript的自动分号插入机制在return的后面强行加了一个分号,于是该函数就return了一个undefined。这导致javascript写花括号不能换行。在其它语言中,这是难以想象的。如何规避这个机制众说纷纭,但我们一般都是在该加分号的地方全部都加上分号。并且,花括号之前不要换行。真希望这个语法被取消掉。
无论在程序的什么位置,不用var/const/let,直接赋值变量,则定义了一个全局变量。
function func(){
x = 10; // x是全局变量
}
禁止使用这种语法。不仅如此,也要禁止使用全局变量。因为一旦忘记写var/const/let,程序就引入了一个未知的行为,但要找到问题出在哪一行却犹如大海捞针。幸好后来的严格模式禁止了这种语法。建议永远使用严格模式。
在早期,只能用这个关键字来定义变量。但是,这个关键字定义出来的变量居然没有块域。
{
var x = 10;
}
console.log(x); // 10
它跟下面的语句等价。
var x = 10;
console.log(x); // 10
我们甚至还可以这样。
console.log(x); // undefined
{
var x = 10;
}
变量x可以先被使用(虽然值为undefined),然后再被定义出来。它跟下面的语句等价。
var x;
console.log(x); // undefined
x = 10;
也就是说,var定义的变量,其实编译器把它悄悄的放到了第一行,在定义的那一行再进行初始化操作。如此诡异的语法,除了javascript之外,还真没有其它语言采用。Javascript还为这个特性取了一个名字,叫做“变量提升”。 神奇的是,var定义的变量虽然没有块域,但是却有函数域。
function func(){
var x = 10;
}
console.log(x); // error: x is not defined
为了让var表现得好像有块域一样,一个特有的语法被发明出来,叫做立即执行函数。用这玩意可以把var封锁在函数局部域内。
(function() {
var x = 10; // x只在这个匿名函数内部可见
})();
可惜,立即执行函数会改变this的含义,因此有些地方还是需要做特殊处理。 想要用好var,需要对上面的内容了如指掌。否则稍有不慎就会创造出诡异的bug。因此,永远使用带有块域和函数域的let/const。禁止使用var。
这个函数把字符串作为javascript语句来执行。它的功能过于强大(因而很不安全),因此禁止使用。
如果你完全不知道with语句是做什么的,那么恭喜你,你永远也不需要知道。如果你已经知道with是做什么的,那么赶紧忘掉它。
除了用它来测试javascript引擎是符合标准的之外,完全没有任何用处。
同上,禁用。