第3章 语言基础
3.1 语法
3.1.1 区分大小写
字符识别区分大小写,别占用关键字
3.1.2 标识符
所谓标识符,就是变量、函数、属性或函数参数的名称。
标识符第一个字符必须是一个字母、下划线或美元符号$
3.1.3 注释
单行注释和多行注释
3.1.4 严格模式
'use strict'
这是一个预处理指令,目的是不破坏ES3的写法
3.1.5 语句
单条条件语句建议也是用代码块包裹;语句推荐使用分号结尾
3.2 关键字与保留字
关键字不能用来作为标记符或属性名,保留字就是未来的关键字,现在先预留空出
3.3 变量
有三个关键字可以声明变量
3.3.1 var关键字
var声明的范围是函数作用域
-
var声明作用域
使用var操作符定义的变量会成为包含它函数的局部变量。不过在函数内定变量时省略var操作符,可以创建一个全局变量。
虽然可以通过省略var操作符定义全局变量,但不推荐这么做。在局部作用域中定义的全局变量很难维护在严格模式下,这种方式会导致抛出ReferenceError
-
var声明提升
所有变量声明会被拉到函数作用域的顶部
3.3.2 let声明
let声明的范围是块作用域,块作用域是函数作用域的子集
let不允许同一个块作用域中出现冗余声明
-
暂时性死区
let声明的变量不会在作用域中被提升,因此在let声明一个变量之前,不能以任何方式来引用该变量。在let声明之前的执行瞬间被称为暂时性死区
-
全局声明
使用let在全局作用域中声明的变量不会称为window对象的属性
-
条件声明
在使用var声明变量时,由于声明会被提升,JS引擎会自动将多余的声明在作用域顶部合并为一个声明。
-
for循环中的let声明
使用let声明迭代变量时,JS引擎在后台会为每个迭代循环声明一个新的迭代变量。
3.3.3 const声明
const行为与let基本相同,唯一一个重要的区别是用它声明变量时必须同时初始化变量,且尝试修改const声明的变量会导致运行时错误
const声明的限制只适用于它指向的变量的引用。换句话说,如果const变量引用的是一个对象,那么修改这个对象内部的属性并不违反const的限制
### 3.3.4 声明风格及最佳实践
1.不适用var
- const优先,let次之
3.4 数据类型
ECMAScript有6种简单的数据类型:Undefined、Null、Boolean、Number、String、Symbol
一种复杂数据类型Object
3.4.1 typeof 操作符
测试数据的类型
3.4.2 undefined类型
当var和let声明了变量但是没有赋值,被声明的变量默认为赋值为undefined
3.4.3 null类型
逻辑上讲null值表示一个空对象指针。null与undefined的不同之处在于,我们不需要去显示把变量值设置为undefined,但我们在创建对象的时候,可以用null填充,标明这是一个对象类型。
const a = {}
const b = null
console.log(typeof a)
console.log(typeof b)
这两种方式输出的结果都为object
3.4.4 Boolean类型
true,false
数据类型 | 转换为true的值 | 转换为false的值 |
---|---|---|
String | 非空字符串 | 空字符串 |
Number | 非零数值(包括无穷值) | 0、NaN |
Object | 任意对象 | null |
Undefined | N/A | undefined |
3.4.5 Number类型
-
浮点值
-
值的范围
最小值保存在Number.MIN_VALUE,最大值保存在Number.MAX_VALUE。超出了范围被自动转成一个特殊的Infinity
-
NaN
not a number,用于表示本来要返回数值的操作失败了(而不是抛出异常)
-
数值转换
有三个函数可以把非数值转换为数值:
Number()、parseInt()、parseFloat()
3.4.6 String类型
- 字符字面量
字面量 | 含义 |
---|---|
\n | |
\t | |
\b | |
\r | |
\f | |
\\ | |
\’ | |
\" | |
\xnn | |
\unnnn |
- 字符串的特点
字符串是不可变的,意思是一旦创建,它们的值就不能变了。要修改某个变量中的字符串值,必须先销毁原始的字符串,然后将包含新值的另一个字符保存到该变量。
-
转化为字符串
有两种方式把一个值转为字符串。一个
toString()
,一个String()
。区别在于
String()
可以把undefined
和null
转为字符串。 -
模板字面量
模板字面量保留换行符,可以跨行定义字符串。
-
字符串插值
${}
所有插入的值都会使用
toString()
强制转型为字符串 -
模板字面量标签函数
模板函数会获取字符模板与传入参数。
-
原始字符串、
使用
String.raw
函数获取原始模板字面量的值
3.4.7 Symbol类型
中文叫符号。符号实例是唯一、不可变的。用途是确保对象属性使用唯一标识符,不会发生属性冲突的危险
-
符号的基本用法
符号需要使用
Symbol()
函数初始化Symbol()
函数不能与new
关键字一起作为构造函数使用。这样做是为了避免创建符号包装对象 -
使用全局符号注册表
如果运行时的不同部分需要共享和重用符号实例,那么可以用一个字符串作为键,在全局符号注册表中创建并重用符号
为此需要使用
Symbol.for()
方法Symbol.for()
对每个字符串键都执行幂等操作。(幂等操作:用户对同一操作发起的一次请求或者多次请求的结果是一致的,不会因为多次点击而产生了副作用)
还可以使用
Symbol.keyFor()
来查询全局注册表,这个方法接受符号,返回该全局符号对应的字符串键。如果查询的不是全局符号,则返回undefined -
使用符号作为属性
-
常用内置符号
-
Symbol.asyncIterator
这个符号作为一个属性表示“一个方法,该方法返回对象默认的AsyncIterator。由for-await-of语句使用”。换句话说这个符号表示实现异步迭代器API的函数
-
Symbol.hasInstance
这个符号作为一个属性表示“一个方法,该方法决定一个构造器对象是否认可一个对象是它的实例。由instanceof操作符使用”。instanceof操作符可以用来确定一个对象实例的原型链上是否有原型。
-
Symbol.isConcatSpreadable
这个符号作为一个属性表示"一个布尔值,如果是true,则意味着对象应该用Array.prototype.concat()打平其数组元素"
-
Symbol.iterator
这个符号作为一个属性表示“一个方法,该方法返回对象默认的迭代器。由for-of语句使用”
-
Symbol.match
这个符号作为一个属性表示“一个正则表达式方法,该方法用正则表达式去匹配字符串。由
String.prototype.match()
方法使用”
-
-
Symbol.replace
这个符号作为一个属性表示“一个正则表达式方法,该方法替换一个字符串中匹配的子串。由
String.prototype.replace()
方法使用” -
Symbol.search
这个符号作为一个属性表示“一个正则表达式方法,该方法返回字符串中匹配正则表达式的索引。由
String.prototype.search()
方法使用” -
Symbol.species
这个符号作为一个属性表示“一个函数值,该函数作为创建派生对象的构造函数”
-
Symbol.split
这个符号作为一个属性表示“一个正则表达式方法,该方法在匹配正则表达式的索引位置拆分字符串。由
String.prototype.split()
方法使用” -
Symbol.toPrimitive
这个符号作为一个属性表示“一个方法,该方法将对象转换为相应的原始值。由
ToPrimitive
抽象操作使用” -
Symbol.toStringTag
这个符号作为一个属性表示“一个字符串,该字符用于创建对象的默认字符串描述。由内置方法
Object.prototype.toString()
使用” -
Symbol.unscopables
这个符号作为一个属性表示"一个对象,该对象所有的以及继承的属性,都会从关联对象的with环境绑定中排除"
3.4.8 Object类型
对象是一组数据和功能的集合。对象通过new操作符后跟对象类型的名称来创建。
let o = Object()
3.5 操作符
3.5.1 一元操作符
只操作一个值的操作符叫一元操作符。
-
递增/递减操作符
照搬C语言的,前缀版和后缀版两种
-
一元加和减
3.5.2 位操作符
-
按位非
-
按位与
-
按位或
-
按位异或
-
有符号右移
-
无符号有移
3.5.3 布尔操作符
-
逻辑非
-
逻辑与
逻辑与操作符是一种短路操作符,意思就是第一个操作数决定了结果,那么永远不会对第二个操作数求值
-
逻辑或
3.5.4 乘性操作符
- 乘法操作符
- 除法操作符
- 取模操作符
3.5.5 指数操作符
**等价于Math.pow()
3.5.6 加性操作符
- 加法操作符
- 减法操作符
3.5.7 关系操作符
四种,返回类型为布尔值
3.5.8 相等操作符
- 等于和不等于
- 全等和不全等
区别在于等于和不等于会对操作数进行强制类型转换,全等于和不全等不会。
3.5.9 条件操作符
xxx = xx > yy ? xx:yy
3.5.10 赋值操作符
3.5.11 逗号操作符
一条语句执行多个操作
3.6 语句
3.6.1 if语句
3.6.2 do-while语句
后测试循环语句
3.6.3 while语句
先测试循环语句
3.6.4 for语句
先测试循环语句
初始化定义的迭代器变量在循环执行完成后几乎不可能再用到了。因此,最清晰的写法是使用let声明迭代器变量,这样就可以将这个变量的作用域限定在循环中
3.6.5 for-in语句
用于枚举对象的属性
3.6.6 for-of语句
用于遍历可迭代对象的元素
3.6.7 标签语句
给语句加标签,可以在后面通过break或者continue语句引用。典型应用场景是嵌套循环
3.6.8 break和continue语句
3.6.9 with语句
3.6.10 switch语句
3.7 函数
function a(){
console.log("a")
}
3.8 小结
六个基本类型,一个复杂类型
不区分浮点值和整数,只有Number
一种数值数据类型
不指定返回值的函数实际上会返回特殊值undefined