目录
1. 自动分号插入(ASI)
JavaScript 有一个自动分号插入机制,它会在某些情况下自动为代码添加分号。这可能会导致一些意外的行为。
function getValue() {
return
{
name: 'John'
};
}
console.log(getValue()); // 输出: undefined
//在这个例子中,由于自动分号插入,
//return 语句后面被自动添加了分号,
//使得 { name: 'John' } 这部分代码没有被返回,函数返回了 undefined。
浏览器输出结果:
2. 宽松相等(==
)和严格相等(===
)
==
会在比较之前进行类型转换,而 ===
不会。这可能会导致一些反直觉的结果。
console.log(0 == false); // 输出: true
console.log('' == false); // 输出: true
console.log(null == undefined); // 输出: true
console.log(0 === false); // 输出: false
console.log('' === false); // 输出: false
console.log(null === undefined); // 输出: false
3. 函数参数默认值的奇怪行为
在 JavaScript 中,函数参数的默认值是在函数调用时计算的,而不是在函数定义时。
let x = 1;
function foo(y = x) {
return y;
}
console.log(foo()); // 输出: 1
x = 2;
console.log(foo()); // 输出: 2
4. 数组的 length
属性可写
JavaScript 数组的 length
属性是可写的,修改它可以改变数组的长度。
let arr = [1, 2, 3];
console.log(arr.length); // 输出: 3
arr.length = 2;
console.log(arr); // 输出: [1, 2]
arr.length = 5;
console.log(arr); // 输出: [1, 2, empty × 3]
浏览器输出结果:
5. 变量提升
在 JavaScript 中,变量和函数声明会被提升到当前作用域的顶部。这意味着你可以在变量或函数声明之前使用它们。
console.log(x); // 输出: undefined
var x = 10;
foo(); // 输出: "Hello!"
function foo() {
console.log("Hello!");
}
6. 函数作用域和块级作用域
在 ES6 (ECMAScript 2015)之前,JavaScript 只有函数作用域,没有块级作用域。使用 var
声明的变量会 “逃出” 块级作用域。
if (true) {
var y = 20;
}
console.log(y); // 输出: 20
而使用 let
和 const
声明的变量具有块级作用域。
if (true) {
let z = 30;
}
// console.log(z); // 报错: z is not defined
浏览器输出结果:
7. NaN
的特殊性
NaN
(Not a Number)是一个特殊的值,它不等于任何值,包括它自己。
console.log(NaN === NaN); // 输出: false
console.log(isNaN(NaN)); // 输出: true
8. 隐式类型转换
JavaScript 在进行某些运算时会进行隐式类型转换,这可能会导致一些意想不到的结果。
console.log('5' + 3); // 输出: "53"
console.log('5' - 3); // 输出: 2