1. let 声明变量
let 声明变量与var类似,但略有不同
1.1 let声明的变量只在当前let命令所在的代码块有效
{
let myName = 'Ably';
var myAge = 22;
console.log(myName) // Ably
console.log(myAge) // 22
}
console.log(myName) // 报错 myName is not defined
console.log(myAge) // 22
1.2 let不存在变量提升,var才存在变量提升
console.log(myName) // undefined
var myName = 'Ably'
console.log(myAge) // 报错 Cannot access 'myAge' before initialization
let myAge = 22
1.3 暂时性死区(temporal dead zone,简称 TDZ)。
只要块级区域内存在let声明变量,那么其他位置声明的变量将不再对其产生影响
if (true) {
// TDZ开始
tmp = 'abc'; // ReferenceError
console.log(tmp); // ReferenceError
let tmp; // TDZ结束
console.log(tmp); // undefined
tmp = 123;
console.log(tmp); // 123
}
function bar(x = y, y = 2) {
return [x, y];
}
bar(); // 报错 Cannot access 'y' before initialization
function bar(x = 2, y = x) {
return [x, y];
}
bar(); // [2, 2]
// 报错
let x = x;
// ReferenceError: x is not defined
1.4 不允许重复声明
- 如果用let在块中声明变量,则不可以再次通过let/var的形式声明变量
{
let myName = "Ably";
var myName = "AAbly"
} // 报错 Identifier 'myName' has already been declared
{
let myName = "Ably";
let myName = "AAbly"
} // 报错 Identifier 'myName' has already been declared
- 函数内部不允许重新通过let声明参数
function func(arg) {
let arg;
}
func() // 报错
function func(arg) {
{
let arg;
}
}
func() // 不报错
2. const 声明常量
2.1 声明时必须赋值初始化
const myName; // 报错 Missing initializer in const declaration
2.2 常量声明后不可修改
const myName = "Ably";
myName = "AAbly"
console.log(myName) // 报错 Assignment to constant variable.
2.3 声明对象时地址不可变,但对象属性可以
const myself = {}
myself.name = "Ably";
myself.age = 22;
console.log(myself) // { name: 'Ably', age: 22 }
myself = {
name: "Ably",
age: 22
}
console.log(myself) // 报错 Assignment to constant variable.
- Object.freeze() 冻结对象,添加属性无效
const myself = Object.freeze({})
myself.name = "Ably";
myself.age = 22;
console.log(myself) // {}
块级作用域、暂时性死区、不允许变量提升、不允许重复声明这几点,const与let是相同的。
3. 变量的解构赋值
3.1 只要等号两边的模式相同,左边的变量就会被赋予对应的值。
若解构失败,则未对应值的变量会返回undefined,相当于声明但是并未赋值。
3.2 对象的解构与数组有一个重要的不同。数组的元素是按次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值。
let [name, age, hobby, [firstname, lastname], {aa:bb}, ,cc] = ['Ably', 12, ['badminton', 'backetball'], ['first', 'last'], {aa: 'BB'}, 'CC'];
console.log(hobby) // ['badminton', 'backetball'],
console.log(firstname) // first
console.log(bb) // BB 对象的key要相同,值是可以用变量的
console.log(cc) // undefined 若赋值处CC前有值,则cc对应CC
3.3 剩余变量 ...
let [name, ...hobby] = ['Ably', 'badminton', 'basketball', 'volleyball'];
console.log(name) // Ably
console.log(hobby) // [ 'badminton', 'basketball', 'volleyball' ]
console.log(...hobby) // badminton basketball volleyball
- 上述示例左边是[]内放置变量,右边是[]内放置数值,外观完全相同,若等号右边是字符串,则会将字符串解构
const [myName, myAge] = "Ably 12"
console.log(myName) // A
console.log(myAge) // b
const [myName, myAge] = "Ably12"
console.log(myName) // A
console.log(myAge) // b
const [myName, myAge, [myhobby1, myhobby2], xxx] = "Ably 12"
console.log(myName) // A
console.log(myAge) // b
console.log(myhobby1) // l
console.log(myhobby2) // undefined 没有对应数组类型
console.log(xxx) // y
3.4 右侧必须为iterable类型,不然解构会报错 xx is not iterable
// 报错
let [foo] = 1;
let [foo] = false;
let [foo] = NaN;
let [foo] = undefined;
let [foo] = null;
let [foo] = {};
- 对象嵌套赋值
let obj = {};
let arr = [];
({ foo: obj.prop, bar: arr[0] } = { foo: 123, bar: true });
obj // {prop:123}
arr // [true]
3.5 解构赋值可以有默认值,当右侧的变量值严格等于undefined时,才会使用默认值
3.6 字符串长度
let {length : len} = 'hello';
len // 5
3.6 一个难忘的示例
- 目前还没想好如何解释这两个函数的差异,先记住吧
3.7 用途
- 交换变量值
let x = 1;
let y = 2;
[x, y] = [y, x];
console.log(x, y) // 2 1
- 所得数据解构
// 返回数组
function example() {
return [1, 2, 3];
}
let [a, b, c] = example();
// 返回对象
function example() {
return {
foo: 1,
bar: 2
};
}
let { foo, bar } = example();
4. 字符串扩展
4.1 字符的Unicode表示法
- ES6加强了对Unicode的支持,允许采用\uxxxx形式表示一个字符,其中xxxx表示字符的Unicode码点
eg1:
"\u0061" -> "a"
"\u0068" -> "h"
- 但是,这种表示法只限于码点在\u0000 ~ \uFFFF 之间的字符。超出这个范围的字符,必须要用两个双字节的形式来表示。
"\uD842\uDFB7"
// "𠮷"
- \u后面跟上超过0xFFFF的数值(比如\u20BB7),JavaScript会理解成\u20BB+7,变成本身\u20BB的内容拼接上7
"\u20BB" -> '₻'
"\u20BB7" -> '₻7'
ES6对此问题进行了改进,只要将后续的码点放入大括号内,就能正确解读该字符信息
"\u{20BB7}" -> '𠮷'
"\u{41}\u{42}\u{43}"
// "ABC"
let hello = 123;
hell\u{6F} // 123
'\u{1F680}' === '\uD83D\uDE80'
// true
- 上面代码中,最后一个例子表明,大括号表示法与四字节的UTF-16编码是等价的。有了这种表示法之后,JavaScript共有6中方法可以表示一个字符。
'\z' === 'z' // true
'\172' === 'z' // true
'\x7A' === 'z' // true
'\u007A' === 'z' // true
'\u{7A}' === 'z' // true
4.2 字符串的遍历器接口
- ES6为字符串添加了遍历器接口,使得字符串可以被for…of 循环遍历。
for (let codePoint of 'hello world') {
console.log(codePoint)
}
// "h" "e" "l" "l" "o" " " "w" "o" "r" "l" "d"
- 除了遍历字符串,这个遍历器最大的优点是可以识别大于0xFFFF的码点,传统的for循环无法识别这样的码点
let text = String.fromCodePoint(0x20BB7)
console.log(text) // 𠮷
console.log(text.length) // 2
for(let i = 0; i < text.length; i++){
console.log(text[i])
}
// 上述普通for循环,返回两个无法识别的字符
// �
// �
for(let str of text){
console.log(str)
}
// 𠮷
- 上述代码中,字符串text解析后可发现只有一个字符,但是for循环会认为它包含两个字符,length方法也是,而for…of 循环会正确识别最终字符
4.3 直接输入U+2028和U+2029
JavaScript规定有5个字符,不能在字符串里面直接使用,只能使用转义形式。
- U+005C:反斜杠 (reverse solidus)
- U+000D:回车
- U+2028:行分隔符
- U+2029:段分隔符
- U+000A:换行符
4.4 JSON.stringify()的改造
根据标准,JSON数据必须是UTF-8编码。但是,现在的JSON。stringify()方法有可能返回不符合UTF-8标准的字符串。
具体来说,UTF-8 标准规定,0xD800到0xDFFF之间的码点,不能单独使用,必须配对使用。比如,\uD834\uDF06是两个码点,但是必须放在一起配对使用,代表字符𝌆。这是为了表示码点大于0xFFFF的字符的一种变通方法。单独使用\uD834和\uDF06这两个码点是不合法的,或者颠倒顺序也不行,因为\uDF06\uD834并没有对应的字符。
JSON.stringify()的问题在于,它可能返回0xD800到0xDFFF之间的单个码点。
JSON.stringify('\u{D834}') // "\u{D834}"
为了确保返回的是合法的 UTF-8 字符,ES2019 改变了JSON.stringify()的行为。如果遇到0xD800到0xDFFF之间的单个码点,或者不存在的配对形式,它会返回转义字符串,留给应用自己决定下一步的处理。
JSON.stringify('\u{D834}') // ""\\uD834""
JSON.stringify('\uDF06\uD834') // ""\\udf06\\ud834""
4.5 模板字符串
- 模板字符串时增强版的字符串,用反引号`标识。它可以当做普通字符串使用,也可以将字符串和变量通过${变量}的形式拼接在一起。
const myName = "Ably";
const myAge = 23;
let myIntro = `Hello, my name is ${myName}, I am ${myAge} years old`
console.log(myIntro) // Hello, my name is Ably, I am 23 years old
- 模板字符串中如果还需要使用`,需要使用反斜杠\对反引号进行转义,不然会发生报错
console.log(`Hell\`o w\`orld`) // Hell`o w`orld
- 如果使用模板字符串表示多行字符串,所有的空格和缩进都会保留在输出之中,如果不想要,可以通过.trim()方法消除它。
- 模板字符串中
${}
内部可以写变量,也可以进行运算,操作对象属性,还可以调用函数 - 模板字符串中
${}
内部可以继续嵌套模板字符串
4.6 模板编译
通过模板字符串,生成正式模板的实例如下:
let template = `
<ul>
<% for(let i = 0; i < data.supplies.length; i++) { %>
<li><%= data.supplies[i] %</li>
<% } %>
</ul>
`;
上面代码在模板字符串之中,放置了一个常规模板。该模板使用<%…%>放置JavaScript代码,使用<%=…%>输出JavaScript表达式。
应该如何编译这个模板字符串呢?
一种思路是将其转换成为JavaScript表达式字符串
5. 字符串新增方法
6. 正则的扩展
7. 数值的扩展
7.1 数值分隔符
- ES2021,允许JavaScript的数值使用下划线
_
作为分隔符,增加数字的可读性
console.log(1_000_000_000 === 1000000000)
function formatLargeNumber(num){
return num.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1_')
}
const res = formatLargeNumber(1000000000)
console.log(res, "最终结果") // 1_000_000_000 最终结果
console.log(typeof res) // string
- 三个将字符串转成数值的函数,不支持数值分隔符
- Number()
- parseInt()
- parseFloat()
7.2 Number.isFinite(),Number.isNaN()
- 参数类型不是数值/参数为Infinity/-Infinity,Number.isFinite一律返回false。
- 如果参数类型不是NaN,Number.isNaN一律返回false。
7.3 Number.parseInt(),Number.parseFloat()
总结用法,希望可以帮助到你,
我是Ably,你无须超越谁,只要超越昨天的自己就好~