一、let 和 const 命令
let 命令
- let 与 var 的区别:let 声明的变量只在 let 命令所在的代码块中有效
- let 不存在变量提升
- 因此会有暂时性死区
- 暂时性死区也意味着
typeof
不再是百分百安全的操作
块级作用域
- ES5 只有全局作用域和函数作用域,没有块级作用域,这带来很多不合理的场景:内层变量可能会覆盖外层变量(if 里的var 变量提升到 if 外);用来计数的循环变量泄露为全局变量。
- let 使得 es 有了块级作用域
- 在块级作用域中声明函数,理论和实际:es5 不允许,浏览器不听;es6 允许,规定其行为类似 let,在作用域外不可引用,浏览器不听,为了降低兼容问题,es6 的浏览器让其行为类似 var,会变量提升,但 es6 的其它环境遵守规定。
- 考虑到环境导致差异太大,应避免在块级作用域中声明函数,如果非要,也应写成函数表达式的形式,而非函数声明。
const 命令
- const 的作用域与 let 相同
- es6 声明变量共有 6 种方法:
es5 的 var
function
es6 的 let
const
class
import
顶层对象
- 浏览器的
window
,Node 的 global
,全局作用域定义的变量会成为顶层对象的属性,这不合理
- 所以 ES6 规定
let
const
class
定义的全局变量不属于顶层对象的属性,var
和 function
为了兼容保持不变
- 怎样获取顶层对象,浏览器是
window
,Node 是 global
,浏览器 和 Web Worker 中 self
也指向顶层对象
- 获取顶层对象的环境差异太大,ES2020 引入
globalThis
作为(指向)顶层对象
二、变量的解构赋值
let [a, b, c] = [0, 1, 2]
a // 0
b // 1
c // 2
let [head, ...tail] = [1, 2, 3, 4]
head // 1
tail // [2, 3, 4]
// 默认值
let [x = true] = []
x // true
// 默认值是 值 === undefined 时触发
let [x = true] = [null]
x // null
// 如果变量名与属性名不一致,要这样写
let { foo: baz } = { foo: 'aaa', bar: 'bbb' }
baz // 'aaa'
foo // error: foo is not defined
const [a, b, c, d, e] = 'hello'
a // 'h'
let { length: len } = 'hello'
len // 5
let { toString: s } = 123
s === Number.prototype.toString // true
- 解构赋值的规则是,如果等号右边不是对象或数组,就先将其转为数组,
null
和 undefined
无法转为数组,因此对他们解构赋值会报错
let { prop: x } = undefined // TypeError
let { prop: y } = null // TypeError
用途
- 引入模块的指定方法
- 函数参数的定义
- 函数参数的默认值
- 从函数返回多个值
- 交换变量的值
- 提取 JSON 数据
- 遍历 Map 结构
// 任何部署了 Iterator 接口的对象都可以使用 for...of 循环遍历
// 搭配解构赋值,获取键名和键值更加方便
const map = new Map()
map.set('first', 'hello')
map.set('second', 'world')
for (let [key, value] of map) {
console.log(key + ' is ' + value)
}
// first is hello
// second is world
三、字符串的扩展
- 字符的 Unicode 表示法:
\u{20BB7}
- 给字符串添加了
Iterator 接口
,使其可以用for...of
遍历
- 模板字符串
- 标签模版
- 标签模版带参数
四、字符串的新增方法
String.fromCodePoint()
- 可以识别大于
\uFFFF
的码点
- 是对
String.fromCharCode()
的升级
- 作用与
str.codePointAt()
相反
String.row()
- 返回一个斜杠被转义的字符串
- 是专用于模板字符串的标签函数
str.codePointAt()
- 比较:
charCodeAt()
- 对于32位的 UTF-16 编码的字符,可以正确返回大于
\xFFFF
的值,但长度还是2
- 要正确识别长度,可使用
for of
或者使用 ...
展开运算
str.normalize()
- unicode 正规化
- 合成符号的概念
- 四个参数
- 不能识别中文
str.includes
str.startsWith
str.endsWith
- 返回布尔值,均支持第二个参数,表示开始检索的位置
- 原有的
indexOf
用来查看字符串是否包含在另一个字符串之中
str.repeat()
- 返回一个字符串,是原字符串重复n遍
- 小数参数会被向下取整
- 参数是
Infinity
或 负数会报错
str.padStart()
str.padEnd()
- 补全长度
- 接收两个参数,第一个是长度,第二个是用于补全的字符串
- 省略第二个参数会用空格来补全
str.trimStart()
str.trimEnd()
str.matchAll()
str.replaceAll()
- 和 replace 一样,返回新字符串,不改变原字符串
- 第二个参数中的特殊字符串:
$&
$`
$'
$n
$$
五、正则的扩展
- 构造函数的扩展,允许
var reg = new RegExp(/xyz/ig, 'i')
形式(即第一个参数是表达式的情况下,允许第二个参数将 flags 覆盖),会等同于 var reg = /xyz/i
- u 修饰符
reg.unicode
- y 修饰符
reg.sticky
- s 修饰符
reg.dotAll
-
reg.source
reg.flags
- 后行断言
- Unicode 属性类
- 具名组匹配
-
str.matchAll()
返回的是遍历器 Iterator
转为数组很简单:
// 法一
[...str.matchAll(regexp)]
// 法二
Array.from(str.match(regexp))
六、数值的扩展
- 二进制
0b
和八进制 0o
表示
-
Number.isFinite()
是否是有限的,对于非数值,都返回 false
-
Number.isNaN()
只对 NaN
返回 true
- 而全局函数
isFinite()
和 isNaN()
会先把非数值参数转为数值
-
Number.parseInt()
Number.parseFloat()
与全局函数无差,是为了让方法回归到模块本身
-
Number.isInteger()
判断是否是整数,对非数值返回 false
,精度超出限制会误判
-
Number.EPSILON
极小的常量 Number.EPSILON === Math.pow(2, -52)
- JS 能表示的整数在
-2^53
到 2^53
之间(不含两端),超出这个范围则无法精确表示这个值
Number.MAX_SAFE_INTEGER
最大安全整数,等于 2^53 - 1
Number.MIN_SAFE_INTEGER
最小安全整数,等于 -2^53 + 1
Number.isSafeInteger()
判断整数是否在这个范围内,非整数返回 false
- Math 新增 17 个静态方法
- 指数运算符
2 ** 3 === 8
-
BigInt
:第八种数据类型,数值加后缀 n 表示
前七种:Undefined Null Boolean String Number Object Symbol
网友评论