奇奇怪怪的 JavaScript

1,147 阅读2分钟

函数表达式和函数声明

// 函数声明语句
foo(); // ok
function foo() {}
// 函数表达式语句
foo(); // Uncaught TypeError: foo is not a function
var foo = function() {}

函数声明,会在执行当前作用域的代码之前执行完毕。

而函数表达式,只有处理器真正遇到这段代码的时候才会执行。

.sort() 的默认行为

arr = [11, 10, 3, 2, 1]
arr.sort() // [1, 10, 11, 2, 3]

默认情况下,sort() 会将元素转换成字符串,然后对字符串进行升序排序🤧。

如果要对数字进行排序,需要传入自定义的对比函数。

arr = [11, 10, 3, 2, 1]
arr.sort((a, b) => a - b) // [1, 2, 3, 10, 11]

0.1 + 0.2 ≠ 0.3

0.1 + 0.2 // => 0.30000000000000004
0.1 + 0.2 === 0.3 // => false

这不是 JavaScript 才有的问题,只要是根据 IEEE 754 标准实现的浮点数运算,都会有这个问题。

因为计算机是用二进制来记录数据的, 0.1 转换成二进制变成了 0.0001100110011...(0011无限循环),假设计算时,只保留小数点后4位的话(实际上会保留更多位,但本质是一样的),就变成了 0.0001,此时已经损失了一部分精度,在此基础上进行计算的话,最终的结果和 0.3 就会存在偏差。

如果需要对比小数,可以选择一个具体的精度,对比两数的差值是否在想要的精度范围内。

const PRECISION = 1e-7;
if (Math.abs(a - b) < PRECISION) {
  // a,b 的小数点后 7 位都是相等的
}

反直觉的 ==

'' == []   // true
[] == []   // false
NaN == NaN // false

javascript 同时提供了 ===== ,用于对比数据(当然还有 Object.is())。

=== 同时判断数据的类型和数据的值,只有两者都相等的时候才会返回 true

== 有自己的一套判断规则,根据参与判断的数据类型,还有可能自动进行数据类型转换,再对比转换后的值。具体的规则虽然不复杂,但数量多(因为类型多),具体的规则参阅文档:

262.ecma-international.org/5.1/#sec-11…

[] == [] 便是根据规则:

(1)首先判断 x 和 y 的类型相等

(1.f)然后判断两者并非引用同一个对象,返回 false

WXWorkCapture_1627444377670.png

自动加分号

function foo() {
  return {
    name: 'apple'
  }
}

function bar() {
  return 
  {
    name: 'orange'
  }
}
foo(); // {name: 'apple'}
bar(); // undefined

bar() 之所以返回 undefined,是因为实际运行的代码是这样子的:

function bar() {
  return;
  {
    name: 'orange'
  }
}

return 语句后面被自动加上了分号 ;

所以,平时书写的 JS 代码的时候,推荐主动加上分号,避免不必要的麻烦。

总结

JavaScript 是一门弱类型的脚本语言,跟 C++,Java 等强类型语言比较起来,语法可以说是非常的自由奔放。使用一个变量,不需要提前声明变量的类型。不同数据类型的变量,也可以进行加减乘除的运算(出现了奇奇怪怪的面试题🙄)。 作为一门发展了十几年的语言,JavaScript 在变得越来越好的同时,也有不少历史遗留问题,作为开发者我们还是要注意一下。