Skip to content

《深入理解ES6》笔记 #21

@lfb

Description

@lfb

第一章:块级作用域

  1. var、let、和 const 声明的特点?
  2. var、let、和 const 声明的区别?

使用 var 声明的变量是不存在块级作用域的,使用 var 声明的变量存在变量提升机制,也就是说通过 var 声明的变量,无论在哪里声明,都会提升到当前的作用域顶部声明的变量。

使用 let 和 const 的声明存在块级作用域。块级作用域指在声明的变量只在当前的作用域下有效,而外部是无法访问的。

let 和 const 声明的相同点:

  • 块级作用域
  • 不存在变量提升
  • 不能重复声明
  • 临时死区,如果在声明前读取这些变量会报错

let 和 const 声明的区别:

  • const 声明是一个常量
  • const 声明常量的同时就需要赋值
  • const 声明常量后不能修改

第二章:字符串

新增的方法

  • codePointAt( string ) 返回字符串的指定的位置码位
  • String.fromCodePoint( number ) 传入指定的位置码位返回一个字符串
  • normalize() 把字符串转换为国际标准化,参数有 NFC, NFD, NFKC, NFKD
  • includes( string ) 检测字符串中是否包含传入的字符,返回true和false
  • starsWith(string, @index) 从字符串头部 index string
  • endsWith(string, @index) 从字符串尾部 index 位置开始检测是否匹配传入的字符串 string
  • repeat( number ) 接收一个 number,运算结果让字符串重复的number次,结果不会影响原来的字符串
  • 模板字符串:hello world,作用:
    • 多行字符串
    • 基本的字符串
    • HTML 转义
  • 字符串占位符:字符串需要包含变量时:hello, ${username}!

es5的一些字符串方法

  • indexOf( string ) 从字符首位开始检测传入的 string 字符串的首次出现的位置
  • lastIndexOf( string ) 从字符尾部开始检测传入的 string 字符串的首次出现位置
  • charAt() 返回指定位置的字符
  • charCodeAt() 返回字符串的指定的位置码位
var str = '波波';

str.codePointAt(0); // 27874
String.fromCodePoint(27874); // '波'
str.normalize('NFC');  // '波波'
str.includes('波') // true

var str = 'bobobo!';
str.startsWith('o', 0); // false
str.startsWith('o', 1); // true

str.endsWith('!'); // true

var str = 'bo';
str.repeat(3); // 'bobobo'

var str = `hello
    world!
`
var str = `<h1>hello, ${username}</h1>`

第三章:函数

es6中函数的形参可以设置默认值

function makeRequest(usl, timeout = 2000, callback = function () {}) {
    // TODO
}

es6函数的默认参数对arguments对象保持分离

function getUserInfo(name, age = 10) {
    // 参数默认值不会影响到arguments的对象
    console.log(arguments); //[0: "bo", ..]
    console.log(arguments.length); // 1
}

getUserInfo('bo');

当定义函数的形参不确定时,可以使用es6可以传入不定参数,arguments对象也是能正确的工作

function getUserInfo(name, ...info) {
   console.log(name); // 'bobobo'
   console.log(info); // [18, 'codingmoneky]
   console.log(arguments); // ["bobobo", 18, "codingmonkey"]
}

getUserInfo('bobobo', 18, 'codingmonkey');

使用元属性 new.target 来检测函数是否被 new 关键字调用

function Person(name) {
    console.log(new.target === Person);

    if (typeof new.target !== 'undefined') {
        this.name = name;
        
    } else {
        throw new Error('必须通过 new 关键字调用Person函数')
    }
}

Person('bobobo'); // Error: 必须通过 new 关键字调用Person函数
new PPerson('bobobo'); // 通过

箭头函数:

  • 没有this,super,arguments和new.target绑定
  • 不能使用new关键字调用
  • 没有原型
  • 不可以改变this的绑定
  • 不支持arguments对象
  • 不支持重复的命名参数
let f1 = value => value // 定义一个箭头函数且返回value值,相当于:
var f1 = function(value) {
    return value;
} 

let fn2 = () => {
    return new Promise((resolve, reject) => {

    }).catch(err => {

    })
}

第四章:扩展对象的功能性

对象简写

let fn1 = (name, age) => {
    return {
        name, // 简写,不用写name: name
        age
    }
}

可计算属性名:

let user = {
    ['first name']: 'bobo'
}
console.log(user['first name']); // 'bobo'

新增的方法

  • Object.is(value1, value2): 比较2个值是否相等,和三等符合运算是一样的,特殊的地方:
    • Object.is(+0, -0) 为false
    • Object.is(NaN, NaN) 为true
  • Object.assign(target, source):把源对象复制一个目标对象(浅拷贝)
let target = {};
let source = {
    name: 'bobo',
    like: 'coding'
}
Object.assign(target, source);
console.log(target); // {name: "bobo", like: "coding"}

增强对象的原型

  • Object.getPrototypeOf( obj ) 获取指定的obj对象的原型
  • Object.setPrototypeOf(obj, prototype) 设置对象的原型,第一个参数为对象,第二个参数为设置第一个参数对象的原型对象
function Books(name) {
    this.name = name;
}

function Mobile(name) {
    this.name = name
}

let books = new Books('jsbooks');
Object.getPrototypeOf(books) === Books.prototype // true

// 手动设置books指向Mobile原型
Object.setPrototypeOf(books, Mobile.prototype);

// 设置后发现books的原型对象不再指向Books原型对象了,而是指向Mobile原型对象
Object.getPrototypeOf(books) === Books.prototype // false
Object.getPrototypeOf(books) === Mobile.prototype // true

第五章:解构

对象解构,取对象的值:

let user = {
    name: 'bobobo',
    email: 'itbo@163.com'
}

// 取 name 和 email 属性
let {name, email} = user;

// 如果对象 node 中没有 jobs 属性
let {name, email, jobs} = user;
// 那么 jobs 的值是 undefined,当然也可以赋默认值
let {name, email, jobs = 'codingmonkey'} = user;

// 解构取值且重新命名
let {name: username, email: workEmail} = user;

// 解构取值且重新命名且赋默认值
let {name: username, email: workEmail, jobs: myjobs = 'codingmonkey@yeah.net'} = user;

嵌套对象解构取值:

let node = {
    local: {
        start: {
            line: 1,
            column: 1
        },
        end: {
            line: 10,
            column: 10
        }
    }
};

// 取嵌套的 start 对象
let {local: {start}} = node;
console.log(start.line); // 1
console.log(start.column); // 1

// 取嵌套的 end 对象
let {local: {end}} = node;
console.log(end.line); // 10
console.log(end.column); // 10

// 取嵌套的 start 对象 且重新命名
let {local: {start: localStart}} = node;
console.log(localStart.line); // 1
console.log(localStart.column); // 1

// 取嵌套不存在的 middle 对象且赋值默认值
let {local: {middle = {line: 5, column: 5}}} = node;
console.log(middle.line); // 5
console.log(middle.column); // 5

数组解构

let arr = [1, 2, 3];
let [value1] = arr; 

console.log(value1)  // 1

// 默认值
let arr = [1];
let [value1, value2 = 2] = arr;

// 不定参数
let arr = [1, 2, 3, 4, 5];
let [value1, ...values] = arr;


// 函数不定参数解构
function getUserInfo(name, ...info) {
    // TODO
    let {age, like, jobs = 'codingmonkey'} = info;
}

第六章:Symbol

Symbol代表唯一的ID

// 创建Symbol
let name = Symbol();
let key = Symbol('keys');

const person = {
    [name]: 'bobobo',
    [key]: 'codingmoneky'
}

第七章:Set和Map

Set 类似数组,但Set不允许元素重复。

  • size:获取元素数量。
  • add(value):添加元素,返回 Set 实例本身。
  • delete(value):删除元素,返回一个布尔值,表示删除是否成功。
  • has(value):返回一个布尔值,表示该值是否是 Set 实例的元素。
  • clear():清除所有元素,没有返回值
const s = new Set();
s.add(1).add(2).add(2); // 添加元素

s.size // 2

s.has(1) // true
s.has(2) // true
s.has(3) // false

s.delete(2);
s.has(2) // false

s.clear();
console.log(s);  // Set(0) {}

// 去重
let arr = [1, 2, 3, 4, 3, 4, 5, 6, 6];
let set = new Set([...arr]);

Set 实例的遍历,可使用如下方法

  • keys():返回键名的遍历器。
  • values():返回键值的遍历器。不过由于 Set 结构没有键名,只有键值(或者说键名和键值是同一个值),所以keys()和values()返回结果一致。
  • entries():返回键值对的遍历器。
  • forEach():使用回调函数遍历每个成员
let set = new Set(['aaa', 'bbb', 'ccc']);

for (let item of set.keys()) {
  console.log(item);
}
// aaa
// bbb
// ccc

for (let item of set.values()) {
  console.log(item);
}
// aaa
// bbb
// ccc

for (let item of set.entries()) {
  console.log(item);
}
// ["aaa", "aaa"]
// ["bbb", "bbb"]
// ["ccc", "ccc"]

set.forEach((value, key) => console.log(key + ' : ' + value))
// aaa : aaa
// bbb : bbb
// ccc : ccc

Map 的用法和普通对象基本一致,先看一下它能用非字符串或者数字作为 key 的特性。

Map 实例的属性和方法如下:

  • size:获取成员的数量
  • set(key, value):设置成员 key 和 value
  • get():获取成员属性值
  • has():判断成员是否存在
  • delete():删除成员
  • clear():清空所有
const map = new Map();
map.set('aaa', 100);
map.set('bbb', 200);

map.size // 2

map.get('aaa') // 100

map.has('aaa') // true

map.delete('aaa')
map.has('aaa') // false

map.clear()

Map 实例的遍历方法有

  • keys():返回键名的遍历器。
  • values():返回键值的遍历器。
  • entries():返回所有成员的遍历器。
  • forEach():遍历 Map 的所有成员
const map = new Map();
map.set('aaa', 100);
map.set('bbb', 200);

for (let key of map.keys()) {
  console.log(key);
}
// "aaa"
// "bbb"

for (let value of map.values()) {
  console.log(value);
}
// 100
// 200

for (let item of map.entries()) {
  console.log(item[0], item[1]);
}
// aaa 100
// bbb 200

// 或者
for (let [key, value] of map.entries()) {
  console.log(key, value);
}
// aaa 100
// bbb 200

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions