语言基础

语法

  • ECMAScript 的语法很大程度上借鉴了 C 语言和其他类 C 语言,如 Java 和 Perl

区分大小写
  • ECMAScript 中一切都区分大小写。无论是变量、函数名还是操作符,都区分大小写

标识符
  • 第一个字符必须是一个字母、下划线(_)或美元符号($)
  • 剩下的其他字符可以是字母、下划线、美元符号或数字
  • 推荐小驼峰形式
  • 关键字、保留字、true、false 和 null 不能作为标识符

注释
  • // 单行注释
  • / 多行注释 /

严格模式
  • ES5 增加严格模式,严格模式是一种不同的 JavaScript 解析和执行模型,ECMAScript 3 的一些不规范写法在这种模式下会被处理,对于不安全的活动将抛出错误
  • 启用严格模式,在脚本开头加上这一行 “use strict”

语句
  • ECMAScript 中的语句以分号结尾,即使语句末尾的分号不是必需的,也应该加上
    • 避免输入内容不完整
    • 便于开发者通过删除空行来压缩代码
    • 有助于提升性能

关键字与保留字

  • 关键字

    1. break do in typeof case else instanceof var
    2. catch export new void class extends return while
    3. const finally super with continue for switch yield
    4. debugger function this default if throw delete import try
  • 保留字

    1. enum implements package public interface
    2. protected static let private await

变量

  • ECMAScript 变量是松散类型的,意思是变量可以用于保存任何类型的数据
  • 变量声明:var(所有版本) const let(ES6之后)

var 关键字
  • var 定义变量,在不初始化的情况下,变量会保存一个特殊的值 undefined
  • 定义的变量的值和类型都可以改变
  • 全局声明的变量会成为 window 对象的属性
  • 函数作用域
  • 虽然可以通过省略 var 操作符定义全局变量,但不推荐这么做。在局部作用域中定义的全局变量很难维护,也会造成困惑。这是因为不能一下子断定省略 var 是不是有意而为之。在严格模式下,如果像这样给未声明的变量赋值,则会导致抛出 ReferenceError
  1. function test() {
  2. var message = "hi"; // 局部变量
  3. }
  4. test();
  5. console.log(message); // 出错!
  6. <hr/>
  7. function test() {
  8. message = "hi"; // 全局变量
  9. }
  10. test();
  11. console.log(message); // "hi"
  • 如果需要定义多个变量,可以在一条语句中用逗号分隔每个变量(及可选的初始化),在严格模式下,不能定义名为 eval 和 arguments 的变量,否则会导致语法错误
  1. var message = "hi",
  2. found = false,
  3. age = 29;
  • 存在变量提升
  1. console.log(a) // undefined
  2. var a = 1

let 声明
  • 块作用域
  • 无变量提升,不能在声明前使用变量,暂时性死区
  • 不能重复声明相同变量名
  • for 循环时使用 let ,迭代变量不会渗透到循环体外部

const 声明
  • 类似 let
  • 变量在声明时必须初始化变量,在修改 const 声明的变量会导致运行时错误

声明风格及最佳实践
  • 不使用 var
  • const 优先,let 次之,优先使用 const 来声明变量,只在提前知道未来会有修改时,再使用 let

数据类型

  • 简单数据类型(原始类型):Undefined Null Boolean Number String Symbol(es6新增)
  • 复杂数据类型:Object (Array,Function)

typeof 操作符
  • 对一个值使用 typeof 操作符会返回下列字符串之一:
    • “undefined”表示值未定义
    • “boolean”表示值为布尔值
    • “string”表示值为字符串
    • “number”表示值为数值
    • “object”表示值为对象(而不是函数)或 null
    • “function”表示值为函数
    • “symbol”表示值为符号
  • null 返回的是”object”。这是因为特殊值 null 被认为是一个对空对象的引用
  • 严格来讲,函数在 ECMAScript 中被认为是对象,并不代表一种数据类型。可是,函数也有自己特殊的属性。为此,就有必要通过 typeof 操作符来区分函数和其他对象

Undefined 类型
  • Undefined 类型只有一个值,就是特殊值 undefined。当使用 var 或 let 声明了变量但没有初始化时,就相当于给变量赋予了 undefined 值
  • 对未声明的变量,使用 typeof 返回 的是 undefined
  • 即使未初始化的变量会被自动赋予 undefined 值,但我们仍然建议在声明变量的同时进行初始化。这样,当 typeof 返回”undefined”时,你就会知道那是因为给定的变量尚未声明,而不是声明了但未初始化

Null 类型
  • Null 类型只有一个值,即特殊值 null。逻辑上讲,null 值表示一个空对象指针
  • 在定义将来要保存对象值的变量时,建议使用 null 来初始化,不要使用其他值
  • undefined 值是由 null 值派生而来的 “null == undefined” // true

Boolean 类型
  • Boolean 有两个字面值:true 和 false。这两个布尔值不同于数值,因此 true 不等于 1,false 不等于 0
  • 布尔值字面量 true 和 false 是区分大小写的,因此 True 和 False(及其他大小混写形式)是有效的标识符,但不是布尔值
  • 其他类型的值可以通过 Boolean() 转型函数转换为布尔值

  • | 数据类型 | 转换为 true 的值 | 转换为 false 的值 | | —- | —- | —- | | Boolean | true | false | | String | 非空字符串 | 空字符串(“”) | | Number | 非零数值 | 0 NAN | | Object | 任意对象 | null | | Undefined | N/A(不存在) | undefined |

Number 类型
  • 八进制(0 开头),十六进制(0x 开头)
  • 八进制在严格模式下是无效的,会导致 JavaScript 引擎抛出语法错误
  • 由于 JavaScript 保存数值的方式,实际中可能存在正零(+0)和负零(0)。正零和负零在所有情况下都被认为是等同的
  • 浮点数
    • 必须包含小数点,小数点后没有数字或为0,会被转换为整数
    • 存储浮点数的内存空间是存储整数值的两倍
    • 浮点数的精确度最高可达17位小数 (0.1 + 0.2 != 0.3)
  • 值的范围
    • Number.MAX_VALUE / Number.MIN_VALUE
    • Infinity / -Infinity
  • NaN
    • 表示本来要返回数值的操作失败了(而不是抛出错误)
    • 任何涉及 NaN 的操作始终返回 NaN
    • NaN 不等于包括 NaN 在内的任何值
    • isNaN() 函数,把一个值传给 isNaN()后,该函数会尝试把它转换为数值
  • 数值转换
    • Number()
      • 布尔值,true 转换为 1,false 转换为 0
      • 数值 直接返回
      • null 返回 0
      • undefined 返回 NaN
      • 字符串 包含数值字符,转换为十进制数值;包含十六进制(0x),返回对应的十进制整数值;空字符串返回 0;其他情况返回 NaN
      • 对象,先调用 valueOf() 方法,然后进行转换,如果结果是NaN,调用 toString() 方法,再转换
    • parseInt()
      • 在需要得到整数时可以优先使用 parseInt()函数
      • 字符串最前面的空格会被忽略,从第一个非空格字符开始转换,如果第一个字符不是数值字符,加号或减号,parseInt() 立即返回 NaN,空字符串也返回 NaN
      • 如果第一个字符是数值字符、加号或减号,则继续依次检测每个字符,直到字符串末尾,或碰到非数值字符(包括小数点)
      • 可解析16进制数,如果字符串以”0”开头,且紧跟着数值字符,在非严格模式下会被某些实现解释为八进制整数
      • parseInt()也接收第二个参数,用于指定底数(进制数)
      • 因为不传底数参数相当于让 parseInt()自己决定如何解析,所以为避免解析出错,建议始终传给它第二个参数
    • parseFloat()
      • 从位置 0 开始检测每个字符,解析到字符串末尾或者解析到一个无效的浮点数值字符为止,意味着第一次出现的小数点是有效的,但第二次出现的小数点就无效了
      • parseFloat()只解析十进制值,十六进制数值始终会返回 0
        String 类型
  1. 字符字面量: “\n”(换行) “\t”(制表) “\b”(退格) “\r”(回车) “\f”(换页)
  2. 字符串特点:修改字符串时,会先销毁原始的字符串,然后将包含新值的另一个字符串保存到该变量
  3. 转换为字符串:toString()方法 (null,undefined没有);加号操作符+””
  4. 模板字面量:`` es6新增
  5. 字符串插值:${}

Symbol 类型
  • ES6 新增,确保对象属性使用唯一标识符,不会发生属性冲突的危险
  • 使用 Symbol() 函数创建,可以传入字符串参数作为对符号的描述,可以通过这个字符串调试,但这个字符串参数与符号定义或标识无关
  • 不能与 new 关键字一起作为构造函数使用
  • Symbol.for() 全局符号注册表,采用相同的符号描述,会在注册表中查找,返回该符号实例
  • 全局注册表中的符号必须使用字符串键来创建,因此作为参数传给 Symbol.for()的任何值都会被转换为字符串,空值为 undefined
  • 凡是可以使用字符串或数值作为属性的地方,都可以使用符号

Object 类型
  • 一组数据和功能的集合
  • Object 实例的属性和方法
    • constructor:用于创建当前对象的函数
    • hasOwnProperty(propertyName):用于判断当前对象实例(不是原型)上是否存在给定的属性。要检查的属性名必须是字符串(如 o.hasOwnProperty(“name”))或符号
    • isPrototypeOf(object):用于判断当前对象是否为另一个对象的原型
    • propertyIsEnumerable(propertyName):用于判断给定的属性是否可以使用for-in 语句枚举。与 hasOwnProperty()一样,属性名必须是字符串
    • toLocaleString():返回对象的字符串表示,该字符串反映对象所在的本地化执行环境
    • toString():返回对象的字符串表示
    • valueOf():返回对象对应的字符串、数值或布尔值表示。通常与 toString()的返回值相同

操作符

  • 可用于操作数据值的操作符,在应用给对象时,操作符通常会调用 valueOf()和/或 toString()方法来取得可以计算的值
  1. 一元操作符 只操作一个值的操作符
  1. a = 1 // 1
  2. ++a // 2
  3. a // 2
  4. ..............
  5. b = 1 // 1
  6. b++ // 1
  7. b //2

可作用于字符串,布尔值,对象,可将变量类型转换为数值

  1. a = '01'
  2. b = '1.1'
  3. o = {
  4. valueOf(){
  5. return -1
  6. }
  7. }
  8. a = + a // 值变成数值 1
  9. b = - b // 值变成数值 -1.1
  10. o = + o // 值变成 -1

如果将一元加应用到非数值,则会执行与使用 Number()转型函数一样的类型转换:布尔值 false和 true 转换为 0 和 1,字符串根据特殊规则进行解析,对象会调用它们的 valueOf()和/或 toString()方法以得到可以转换的值

  1. 位操作符

    • ECMAScript中的所有数值都以 IEEE 754 64 位格式存储,但位操作并不直接应用到 64 位表示,而是先把值转换为32 位整数,再进行位操作,之后再把结果转换为 64 位
    • 有符号整数使用 32 位的前 31 位表示整数值。第 32 位表示数值的符号,如 0 表示正,1 表示负。这一位称为符号位(sign bit),它的值决定了数值其余部分的格式
    • 负数以一种称为二补数(补码)的二进制编码存储:绝对值的反码 + 1
    • 按位非(~) 取反 - 1
    • 按位与(&) 都为真时取真
    • 按位或(|) 都为假时取假
    • 按位异或(^)不相同时取真
    • 左移(<<)

      1. oldValue = 2 // 等于二进制 10
      2. newValue = oldValue << 5 // 等于二进制 1000000,十进制 64
    • 右移(>>)

    • 无符号右移(>>>) 右移补 0
  2. 布尔操作符

    • 逻辑非 (!)逻辑非操作符首先将操作数转换为布尔值,然后再对其取反 | 操作数 | true | false | | —- | —- | —- | | 对象 | | √ | | 空字符串 | √ | | | 非空字符串 | | √ | | 0 | √ | | | 非零数值 | | √ | | null | √ | | | NAN | √ | | | undefined | √ | |

    • 逻辑与 (&&) 当第一个操作数为 true 时返回第二个操作数,当第一个操作数为null,NaN,undefined时,直接返回第一个操作数,当第一个操作数为 false 时,不会判断第二个操作数
      - 逻辑或 (||) 当第一个操作数为 true 是返回第一个操作数,不会对第二个操作数进行求值,当第一个操作数为 false 时返回第二个操作数,当两个操作数都是 null,NaN,undefined时,返回 null,NaN,undefined。

    1. 乘性操作符
      • 乘 (*)返回乘积,有操作数为 NaN 时返回 NaN
      • 除 (/)返回商,非零有限位除以0,根据第一个操作数的符号返回 infinity/-infinity
      • 取模/余数 (%),无限值除有限制,有限值除0,返回NaN,有限值除无限值,返回被除数
    2. 指数操作符
      • ES7 新增,Math.pow() 操作符 ``` Math.pow(3,2) // 9 3 2 // 9

squared = 3 squared **= 2 squared // 9

  1. 6. 加性操作符
  2. - (+) 求俩数和,做字符串拼接
  3. - (-) 求俩数差
  4. 7. 关系操作符
  5. - 执行比较两个值的操作,包括小于(<)、大于(>)、小于等于(<=)和大于等于(>=),返回布尔值
  6. - 比较的数中存在数值,则会将另一操作数转换为数值,再进行比较,如果俩操作数都是字符串,则会比较字符串中对应字符的编码,任何关系操作符在涉及比较 NaN 时都会返回 false
  7. 8. 等于操作符
  8. - 等于和不等于 (== / !=),会进行类型转换,当任一操作数为布尔值,则转换为 0/1 后进行比较,如果两者都是对象,当二者指向同一个对象时返回true,否则返回false
  9. - 全等和不全等 (=== / !===) 不会进行类型转换
  10. 9. 条件操作符

variable = boolean_expression ? true_value : false_value

  1. 10. 赋值操作符
  2. - 简单赋值用等于号(=)表示,将右手边的值赋给左手边的变量
  3. 11. 逗号操作符
  4. - 同时声明多个变量
  5. <a name="O5NhC"></a>
  6. #### 语句
  7. - if 语句: if (condition) statement1 else statement2
  8. - do-whiile 语句: 至少执行一次

statement } while (expression);

  1. - while 语句: while(expression) statement
  2. - for 语句 for (initialization; expression; post-loop-expression) statement

let count = 10; for (let i = 0; i < count; i++) { console.log(i); }

  1. 以上代码在循环开始前定义了变量 i 的初始值为 0。然后求值条件表达式,如果求值结果为 truei < count),则执行循环体。因此循环体也可能不会被执行。如果循环体被执行了,则循环后表达式也会执行,以便递增变量 i
  2. - for-in 语句 :用于枚举对象中的非符号键属性,for (property in expression) statement
  3. - for-of 语句:用于遍历可迭代对象的元素,for (property of expression) statement
  4. - 标签语句 label: statement
  5. - break continue 语句 break 立即退出循环,强制执行循环后的下一条语句,continue 立即退出循环,但会再次从循环顶部开始执行
  6. - with 语句:将代码作用域设置为特定的对象,with (expression) statement,由于 with 语句影响性能且难于调试其中的代码,通常不推荐在产品代码中使用 with语句
  7. - switch

switch (expression) { case value1: statement break; case value2: statement break; case value3: statement break; case value4: statement break; default: statement }

  1. 这里的每个 case(条件/分支)相当于:“如果表达式等于后面的值,则执行下面的语句。”break关键字会导致代码执行跳出 switch 语句。如果没有 break,则代码会继续匹配下一个条件。default关键字用于在任何条件都没有满足时指定默认执行的语句(相当于 else 语句)<br />switch 语句可以用于所有数据类型(在很多语言中,它只能用于数值),因此可以使用字符串甚至对象。其次,条件的值不需要是常量,也可以是变量或表达式<br />switch 语句在比较每个条件的值时会使用全等操作符,因此不会强制转换数据类型(比如,字符串"10"不等于数值 10)。
  2. <a name="zdhWh"></a>
  3. #### 函数

function functionName(arg0, arg1,…,argN) { statements } ```

小结

  • ECMAScript 中的基本数据类型包括 Undefined、Null、Boolean、Number、String 和 Symbol
  • 与其他语言不同,ECMAScript 不区分整数和浮点值,只有 Number 一种数值数据类型
  • Object 是一种复杂数据类型,它是这门语言中所有对象的基类
  • 严格模式为这门语言中某些容易出错的部分施加了限制
  • ECMAScript 提供了 C 语言和类 C 语言中常见的很多基本操作符,包括数学操作符、布尔操作符、关系操作符、相等操作符和赋值操作符等
  • 这门语言中的流控制语句大多是从其他语言中借鉴而来的,比如 if 语句、for 语句和 switch语句等

ECMAScript 中的函数与其他语言中的函数不一样

  • 不需要指定函数的返回值,因为任何函数可以在任何时候返回任何值
  • 不指定返回值的函数实际上会返回特殊值 undefined