语法

  1. 严格模式 use strict
    在脚本开头加上这一行:”use strict”;
    ECMAScript 3 的一些不规范写法在这种模式下会被处理,对于不安全的活动将抛出错误。
    也可以单独指定一个函数在严格模式下执行,只要把这个预处理指令放到函数体开头即可:
  1. function doSomething() {
  2. "use strict";
  3. // 函数体
  4. }
  1. 语句

    • 加分号也有助于在某些情况下提升性能,因为解析器会尝试在合适的位置补上分号以纠正语法错误。

      1. let sum = a + b // 没有分号也有效,但不推荐
      2. let diff = a - b; // 加分号有效,推荐
    • 尽量使用代码块

      1. // 有效,但容易导致错误,应该避免
      2. if (test)
      3. console.log(test);
      4. // 推荐
      5. if (test) {
      6. console.log(test);
      7. }

变量

  1. var声明作用域

    • 函数作用域
    • 变量将在函数退出时被销毁

      1. function test() {
      2. var message = "hi"; // 局部变量
      3. }
      4. test();
      5. console.log(message); // 出错!
    • 在函数内部省略var操作符,可以创建一个全局变量

      1. function test(){
      2. message = "hi";
      3. }
      4. test();
      5. console.log(message);

不推荐这么做,可能会造成全局变量污染

  • 如果需要定义多个变量,中间用逗号隔开
    1. var message = "hi",
    2. found = false,
    3. age = 29;

插入换行和空格缩进并不是必需的

  1. var声明变量提升
    使用下面的代码不会报错
  1. function foo() {
  2. console.log(age);
  3. var age = 26;
  4. }
  5. foo(); // undefined
  1. 相当于下面👇的代码
  1. function foo() {
  2. var age;
  3. console.log(age);
  4. age = 26;
  5. }
  6. foo(); // undefined
  1. 这就是所谓的“提升”,也就是把所有变量声明都拉到函数作用域的顶部
  1. let声明

    • let 声明的范围是块作用域
      var声明下👇

      1. if (true) {
      2. var name = 'Matt';
      3. console.log(name); // Matt
      4. }
      5. console.log(name); // Matt
    • let声明下👇 报错:没有定义

      1. if (true) {
      2. let age = 26;
      3. console.log(age); // 26
      4. }
      5. console.log(age); // ReferenceError: age 没有定义
      • 嵌套使用相同的标识符不会报错,而这是因为同一个块中没有声明重复
        1. var name = 'Nicholas';
        2. console.log(name); // 'Nicholas'
        3. if (true) {
        4. var name = 'Matt';
        5. console.log(name); // 'Matt'
        6. }
        7. let age = 30;
        8. console.log(age); // 30
        9. if (true) {
        10. let age = 26;
        11. console.log(age); // 26
        12. }
    • 对声明冗余报错不会因混用let和var而受影响,这两个关键字声明的并不是不同类型的变量,它们只是指出变量在相关作用域如何存在

      1. var name;
      2. let name; // SyntaxError
      3. let age;
      4. var age; // SyntaxError
    1. 暂时性死区
      原因还是let声明的变量不会在作用域中被提升

      1. // name 会被提升
      2. console.log(name); // undefined
      3. var name = 'Matt';
      4. // age 不会被提升
      5. console.log(age); // ReferenceError:age 没有定义
      6. let age = 26;
    2. 全局声明
      使用 let 在全局作用域中声明的变量不会成为 window 对象的属性(var 声明的变量则会)

      1. var name = 'Matt';
      2. console.log(window.name); // 'Matt'
      3. let age = 26;
      4. console.log(window.age); // undefined
    3. 条件声明
      由于let的块级特性,不能依赖条件声明

      1. <script>
      2. let name = 'Nicholas';
      3. let age = 36;
      4. </script>
      5. <script>
      6. // 假设脚本不确定页面中是否已经声明了同名变量
      7. // 那它可以假设还没有声明过
      8. if (typeof name === 'undefined') {
      9. let name;
      10. }
      11. // name 被限制在 if {} 块的作用域内
      12. // 因此这个赋值形同全局赋值
      13. name = 'Matt';
      14. try {
      15. console.log(age); // 如果 age 没有声明过,则会报错
      16. }
      17. catch(error) {
      18. let age;
      19. }
      20. // age 被限制在 catch {}块的作用域内
      21. // 因此这个赋值形同全局赋值
      22. age = 26;
      23. </script>

      4. for 循环中的 let 声明

      使用 let 声明迭代变量时,JavaScript 引擎在后台会为每个迭代循环声明一个新的迭代变量。

      1. for (let i = 0; i < 5; ++i) {
      2. setTimeout(() => console.log(i), 0)
      3. }
      4. // 会输出 0、1、2、3、4

const 声明

const 的行为与 let 基本相同,唯一一个重要的区别是用它声明变量时必须同时初始化变量,且尝试修改 const 声明的变量会导致运行时错误。

数据类型

6中简单的:Undefined、Null、Boolean、Number、String 和 Symbol。
1种复杂的:Object(对象)

typeof 操作符

对一个值使用 typeof 操作符会返回下列字符串之一:

  • “undefined”表示值未定义;
  • “boolean”表示值为布尔值;
  • “string”表示值为字符串;
  • “number”表示值为数值;
  • “object”表示值为对象(而不是函数)或 null;  “function”表示值为函数;
  • “symbol”表示值为符号。
  1. let message = "some string";
  2. console.log(typeof message); // "string"
  3. console.log(typeof(message)); // "string"
  4. console.log(typeof 95); // "number"

调用typeof null 返回的是”object”。这是因为特殊值 null 被认为是一个对空对象的引用

Undefined 类型

不初始化的变量和未定义的变量进行typedof操作得出的答案是一样的都是undefined
定义的变量的时候为了区分开来,尽量赋值初始值

  1. let message; // 这个变量被声明了,只是值为 undefined
  2. // age 没有声明
  3. if (message) {
  4. // 这个块不会执行
  5. }
  6. if (!message) {
  7. // 这个块会执行
  8. }
  9. if (age) {
  10. // 这里会报错
  11. }

永远不必显式地将变量值设置为 undefined
undefined 是一个假值

Null类型

null 值表示一个空对象指针,给typeof 传一个 null 会返回”object”
保存对象值的变量时,建议使用 null 来初始化
undefined 值是由 null 值派生而来的

  1. console.log(null == undefined); // true

null 是一个假值

Boolean 类型

有两个字面值:true 和 false。
Boolean()转型函数:

  1. let message = "Hello world!";
  2. let messageAsBoolean = Boolean(message);

【语言基础】 - 图1

  1. let message = "Hello world!";
  2. if (message) {
  3. console.log("Value is true");
  4. }

Number 类型

Number 类型使用 IEEE 754 格式表示整数和浮点值
十进制

  1. let intNum = 55; // 整数

八进制
必须以0开头

  1. let octalNum1 = 070; // 八进制的 56
  2. let octalNum2 = 079; // 无效的八进制值,当成 79 处理
  3. let octalNum3 = 08; // 无效的八进制值,当成 8 处理

十六进制
必须以0x开头
前缀0x区分大小写,数字中的字母大小写均可

  1. let hexNum1 = 0xA; // 十六进制 10
  2. let hexNum2 = 0x1f; // 十六进制 31
  1. 正零和负零在所有情况下都被认为是等同的

1.浮点值

定义浮点值,必须有小数点

  1. let floatNum1 = 1.1;
  2. let floatNum2 = 0.1;
  3. let floatNum3 = .1; // 有效,但不推荐

因为存储浮点值内存空间是存储整数值的两倍,所以ES想方设法把值转换为整数。

  1. let floatNum1 = 1.; // 小数点后面没有数字,当成整数 1 处理
  2. let floatNum2 = 10.0; // 小数点后面是零,当成整数 10 处理

浮点值的精确度最高可达 17 位小数,但计算时不够精确

  1. if (a + b == 0.3) { // 别这么干!
  2. console.log("You got 0.3.");
  3. }

2.值的范围

  • Number.MAX_VALUE表示最大数值
  • Number.MIN_VALUE表示最小数值
    如果超出了js的范围,则会得到一个Infinity(无穷)值,或者以-Infinity(负无穷大)
    isFinite()函数可以确定一个值是不是有限大
  1. let result = Number.MAX_VALUE + Number.MAX_VALUE;
  2. console.log(isFinite(result)); // false

3.NaN

NaN是一个特殊的值,意思是“不是数值”(Not a Number)
用于表示本来要返回数值的操作失败了(而不是抛出错误)

  • 任何涉及 NaN 的操作始终返回 NaN
  • NaN 不等于包括 NaN 在内的任何值,也就是不能与任何值比较
    1. console.log(NaN == NaN); // false

提供了一个isNaN()函数,判断某个数据是否“不是数值”

  1. console.log(isNaN(NaN)); // true
  2. console.log(isNaN(10)); // false,10 是数值
  3. console.log(isNaN("10")); // false,可以转换为数值 10
  4. console.log(isNaN("blue")); // true,不可以转换为数值
  5. console.log(isNaN(true)); // false,可以转换为数值 1

数值转换

三个函数可以将非数值转换为数值

  • Number()函数
    • 布尔值,true 转换为 1,false 转换为 0。
    • 数值,直接返回。
    • null,返回 0。
    • undefined,返回 NaN。
    • 字符串,只有是数字的时候才返回,非数字返回NaN
    • 空字符串返回0
  1. let num1 = Number("Hello world!"); // NaN
  2. let num2 = Number(""); // 0
  3. let num3 = Number("000011"); // 11
  4. let num4 = Number(true); // 1
  • parseInt()函数
  1. let num1 = parseInt("1234blue"); // 1234
  2. let num2 = parseInt(""); // NaN
  3. let num3 = parseInt("0xA"); // 10,解释为十六进制整数
  4. let num4 = parseInt(22.5); // 22
  5. let num5 = parseInt("70"); // 70,解释为十进制值
  6. let num6 = parseInt("0xf"); // 15,解释为十六进制整数

可以用第二个参数规定传入的进制类型

  1. let num1 = parseInt("10", 2); // 2,按二进制解析
  2. let num2 = parseInt("10", 8); // 8,按八进制解析
  3. let num3 = parseInt("10", 10); // 10,按十进制解析
  4. let num4 = parseInt("10", 16); // 16,按十六进制解析
  • parseFloat()函数
    和上面差不多
  1. let num1 = parseFloat("1234blue"); // 1234,按整数解析
  2. let num2 = parseFloat("0xA"); // 0
  3. let num3 = parseFloat("22.5"); // 22.5
  4. let num4 = parseFloat("22.34.5"); // 22.34
  5. let num5 = parseFloat("0908.5"); // 908.5
  6. let num6 = parseFloat("3.125e7"); // 31250000