JavaScript_ES6中你需要牢记的那些事

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,你无须超越谁,只要超越昨天的自己就好~

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值