文章内容输出来源:拉勾教育Java高薪训练营
概述
ECMAScript 定义了语言层面的规范,包括变量定义、函数声明、逻辑语句等
JavaScript 是 ECMAScript 扩展,在浏览器环境下
- Core - ECMAScript 语言层面实现
- DOM
- BOM
ECMAScript 从 ES5 到 ES6(ES2015) 经历了6年时间,因而新增了很多东西,此后,ECMAScript 保持每年一次的版本迭代,命名按照年份定义,如 ES2015、ES2016 等
块级作用域
ES6 之前只有
- 函数作用域
- 全局作用域
ES6 新增 let、const, 他们 定义的变量只作用于块级作用域
块级作用域产生
- { statement }
此外需要注意
-
for 循环会产生两层嵌套作用域
for(let i = 0; i < 4; i++){ let i = 100; // 输出 100,在循环体作用域内部 i 重新声明了; 如果计数器的 i 和循环体的 i 在一个块级作用域下将会报错; console.log(i); }
在 let const 声明变量之前无法使用变量,不然会报错
解构
/**
*** 数组解构
*/
const arry = [1, 2, 3];
{
const [a, b, c] = arry;
console.log(a, b, c);
}
{
// ...rest 只能出现在最后面
const [a, ...rest] = arry;
console.log(a, rest);
}
{
// 简单应用
let path = "path/router/name";
let [, , name] = path.split("/");
console.log(name);
}
/**
*** 对象解构
*/
const obj = {
a: 1,
b: 2,
c: 3,
name: "",
};
{
const { a, b, c } = obj;
console.log(a, b, c);
}
{
const name = "xiaodaidai";
// 属性重命名
const { name: objName } = obj;
console.log(objName);
}
{
// 属性重命名后赋默认值
const { name: objName = "xiaodaidai" } = obj;
console.log(objName);
}
{
// 简单应用
let { log, dir } = console;
log("log");
dir("dir");
}
模版字符串
- 可以插值、换行、支持表达式
- 带标签的模版字符串
const name = 'xiaodaidai'
const msg = `i love you, ${name}`;
const address = 'jiangsu suzhou';
function tagFun(strings, name, addrss){
// strings 是一个数组,这里就是 result 被 ${name}, ${address} 分割的字符数组
// 打印结果是 [ 'hi, ', ', my address is ', '' ] 'xiaodaidai' 'jiangsu suzhou'
console.log(strings, name, address)
return strings[0] + name + strings[1] + address + strings[2];
}
const result = tagFun`hi, ${name}, my address is ${address}`;
console.log(result)
字符串、对象扩展方法
字符串
- includes
- startsWith
- endsWith
对象
- assign 返回值与 target 相等,可以实现对象浅拷贝
- is 1. 解决数字正负 0 不等; 2. 解决 NaN === NaN false 问题;
-0 === +0 // true
NaN === NaN // false
Object.is(+0, -0); // false
Object.is(NaN, NaN) // true
参数默认值与剩余参数
参数默认值
function defaultParams(paramA, paramB = true) {} // 带有默认值的参数必须在最后面
剩余参数
// ES5
function funA() {
// 通过 arguments 实现
console.log(arguments[0]); // 伪数组
}
// ES6 通过 ... 操作符实现; 只能在参数最后一位且只能使用一次
function funB(...args){
console.log(args[0]);
}
对象字面量增强
const a = 1;
const funA = () => { console.log('this is funA'); };
const obj = {
a, // 属性名称简写
funA, // 方法简写
[Math.random()]: 111 // 计算属性名,属性名可以使用表达式
};
Proxy Reflect
Proxy 对比 Object.defineProperty 优点
- 强大的监听能力
- 可以监视数组方法
- 对原始对象没有侵入
handler 方法 | 触发方式 |
---|---|
get | 读取某个属性 |
set | 写入某个属性 |
has | in 操作符 |
deleteProperty | delete 操作符 |
getPrototypeOf | Object.getPrototypeOf() |
setPrototypeOf | Object.setPrototypeOf() |
isExtensible | Object.isExtensible() |
preventExtensions | Object.preventExtensions() |
getOwnPropertyDescriptor | Object.getOwnPropertyDescriptor() |
defineProperty | Object.defineProperty() |
ownKeys | Object.getOwnPropertyNames()、Object.getOwnPropertySymbols() |
apply | 调用一个函数 |
construct | 用 new 调用一个函数 |
Reflect 对象统一了对象的操作方式
// Reflect 对象统一了对象的操作方式
const objA = {
name: 'xiaozuo',
age: 18,
sex: 0
};
console.log('name' in objA) // true
console.log(delete objA['sex']);
console.log(objA.keys);
// 统一使用 Reflect 内置方法
console.log(Reflect.has(objA, 'name')) // true
console.log(Reflect.deleteProperty(objA, 'age'));
console.log(Reflect.ownKeys(objA));
class Symbol Promise
class 语法示例
class Person {
constructor(name) {
this.name = name;
},
say() {
console.log(`hi,my name is ${this.name}`)
},
// 添加静态方法, 注意 this 内部指向不再指向实例,而是 Person 类型本身
static create(name) {
return new Person(name);
}
}
// new 创建实例
const personA = new Person('xiaozuo');
// 调用静态方法创建实例
const personB = Person.create('xiaodaidai');
/**
* 使用 extends 关键字实现继承
*/
class Student extends Person {
constructor(name, number) {
super(name);
this.number = number
},
hello() {
super().say();
console.log(`my school number is ${this.number}`);
}
}
Symbol 用途
可以给对象定义唯一的键值,避免在扩展第三方模块时候键值冲突
可以给对象定义私有的成员
示例代码
const obj = {
[Symbol('FunA')]: function () {
console.log("test symbol");
},
[Symbol('FunB')]: function () {
console.log("test symbol");
},
};
console.dir(obj);
Promise 是 es6 新增的异步编程的标准,主要的 API
- Promise.resolve()
- Promise.reject()
- Promise.all()
- Promise.race()
Set
示例代码
/**
* Set 示例
*/
(function () {
const s = new Set();
s.add(1).add(2).add(3).add(4); // 添加元素, 链式调用
s.forEach((i) => console.log(i)); // forEach 遍历
// for of 遍历
for (let i of s) {
console.log(i);
}
// 删除
s.delete(1);
// 判断元素是否存在
console.log(s.has(1));
// 清空
s.clear();
// 利用 Set 元素唯一性,数组去重
const arry = [1, 1, 1, 1, 2, 3, 4, 5];
const result = [...new Set(arry)];
console.log(result);
})();
Map
示例代码
/**
* Map 示例
* 与 Object 类似都是键值对,区别是 object 对健只能是字符串
* Map 解决使用对象作为 key 的问题
*/
(function () {
const m = new Map();
const xiaodaidai = { name: "xiaozuo" };
m.set(xiaodaidai, "xiaodaidai");
// API 与 Set 类似 m.has() m.delete() m.clear() m.forEach()
// for of 配合解构遍历 Map
for (let [key, value] of m) {
console.log(key, value);
}
})();
for of
可以遍历
- 数组
- arguments
- dom 获取的伪数组
- Map 、Set 对象
Iterator 迭代器
示例
// 初步认识 Iterator
let arry = [1, 2, 3];
let iterator = arry[Symbol.iterator]();
console.log(iterator.next()); // { value: 1, done: false }
console.log(iterator.next()); // { value: 2, done: false }
console.log(iterator.next()); // { value: 3, done: false }
console.log(iterator.next()); // { value: undefined, done: true }
// 实现可迭代接口
let obj = { // 实现了可迭代接口 iterable, 内部必须实现 Symbol.iterator 方法
arry: [4, 5, 6],
[Symbol.iterator]: function() {
let index = 0;
return { // 实现了迭代器接口 iterator,内部必须实现 next() 方法
next: () => {
return { // 实现了迭代结果接口 iterationResult, 内部要有 value 和 done 属性
value: this.arry[index++],
done: index > this.arry.length
}
}
}
}
};
for(let item of obj) {
console.log(item);
}
// 打印 4 5 6
迭代器模式,使用语言内容提供的统一接口 Symbol.iterator 实现不同数据结构的遍历,让遍历方法与数据结构解耦合
/**
* 迭代器模式
*/
(function(){
const todos = {
life: ['吃饭', '睡觉', '打豆豆'],
work: ['上网', '划水', '写bug'],
learn: ['小说', '电影', '直播'],
// 使用普通方式将遍历与数据解构
each: function(cb) {
let all = [...this.life, ...this.work, ...this.learn];
for(let item of all) {
cb(item);
}
},
// 使用可迭代接口实现解耦合
[Symbol.iterator]: function() {
let index = 0;
let all = [...this.life, ...this.work, ...this.learn];
return {
next() {
return {
value: all[index],
done: index ++ >= all.length
}
}
}
}
};
todos.each(item => {
console.log(`普通方式实现遍历与数据解构:${item}`);
});
for(let item of todos) {
console.log(`可迭代接口实现遍历与数据解构:${item}`);
}
})()
Generator 生成器
生成器是为避免异步编程中回调过深,提供更好的异步编程解决方案;
生成器也可以配合迭代器,简化可迭代接口的实现
示例
// Generator 函数
// 简单示例
function* foo() {
console.log("1111");
yield 100;
console.log("2222");
yield 200;
console.log("3333");
yield 300;
}
const generator = foo();
console.log(generator.next()); // 1111 { value: 100, done: false }
console.log(generator.next()); // 2222 { value: 200, done: false }
console.log(generator.next()); // 3333 { value: 300, done: false }
console.log(generator.next()); // { value: undefined, done: true }
// 简单应用
function* createId() {
let id = 1;
while (true) {
yield id++;
}
}
const idMarker = createId();
console.log(idMarker.next().value);
console.log(idMarker.next().value);
console.log(idMarker.next().value);
/**
* 实现可迭代接口
*/
(function () {
let obj = { // 实现了可迭代接口 iterable, 内部必须实现 Symbol.iterator 方法
arry: [43, 53, 63],
[Symbol.iterator]: function*() {
for(let item of this.arry) {
yield item;
}
}
};
for(let item of obj) {
console.log(item);
}
})();
最后
给出自己用 xmind 整理的知识结构