一、ES6简介
什么是 ECMAScript
ECMAScript 是由 Ecma 国际通过ECMA-262 标准化的脚本程序设计语言。
ES6 兼容性
可查看兼容性:http://kangax.github.io/compat-table/es6/
二、ES6新特性
1、let
关键字来声明变量,特点:
1. 不允许重复声明。
2. 块级作用域。
3. 不存在变量提升。
4. 不影响作用域链
2、const声明常量以及特点
const 关键字用来声明常量,const 声明有以下特点
● 声明必须赋初始值
● 标识符一般为大写
● 不允许重复声明
● 值不允许修改
● 块级作用域
注意:对象属性修改和数组元素变化不会出发 const 错误 应用场景:声明对象类型使用 const,非对象类型声明选择 let
const arr = [1, 2, 3, 4];
arr.push(5, 6);
console.log(arr); // 不报错
const obj = {
uname: 'rick',
age: 30
}
obj.age = 40; // 只要不改变地址,就不报错
3、变量的结构赋值
ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为 解构赋值。
数组的解构赋值
const arr = ['red', 'green', 'blue'];
let [r, g, b] = arr;
对象的解构赋值
const obj = {
uname: 'rick',
age: 30,
sayHi: function () {
console.log('hello');
},
sayBye() {
console.log('Bye~');
}
}
let {name, age, sayHi} = obj;
let {sayBye} = obj;
//当方法被 let {sayBye} = obj; 之后,可以直接使用 sayBye()方法,而不需要obj.sayBye()了。
应用场景:频繁使用对象方法、数组元素,就可以使用解构赋值形式。
4、模板字符串
模板字符串(template string)是增强版的字符串,用反引号 ` 标识,特点:
● 字符串中可以出现换行符
● 可以使用 ${xxx} 形式输出变量,近似 EL 表达式
应用场景:当遇到字符串与变量拼接的情况使用模板字符串。
let name = 'jack';
console.log(`hello, ${name}`);
let ul = `<ul>
<li>apple</li>
<li>banana</li>
<li>peach</li>
</ul>`
5、简化对象写法
ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。这样的书写更加简洁。
应用场景:对象简写形式简化了代码,所以以后用简写就对了。
let uname = 'rick';
let age = 30;
let sayHi = function () {
console.log('Hi');
}
// 创建对象,因属性、方法 的 k v 同名,可以简化
const obj = {
uname,
age,
sayHi() { console.log('Hi'); }
}
6、箭头函数
ES6 允许使用箭头=>定义函数
function 写法
function fn(param1, param2, …, paramN) {
// 函数体
return expression;
}
=> 写法
let fn = (param1, param2, …, paramN) => {
// 函数体
return expression;
}
注意
● 如果形参只有一个,小括号可以省略
● 如果函数体只有一条语句,花括号可以省略,函数的返回值为该条语句的执行结果,如果是 return 语句,return 必须省略
● 箭头函数 this 是静态的,始终指向声明时所在作用域下 this 的值(.call也不能改变)
● 箭头函数不能作为构造函数实例化
● 不能使用 arguments
// 省略小括号
let fn1 = n => {
return n * n;
}
// 省略花括号
let fn2 = (a + b) => a + b;
// 箭头函数 this 始终指向声明时所在作用域下 this 的值
const obj = {
a: 10,
getA () {
let fn3 = () => {
console.log(this); // obj {...}
console.log(this.a); // 10
}
fn3();
}
}
//案例1:箭头函数 this 始终指向声明时所在作用域下 this 的值,call 等方法无法改变其指向
let obj = {
uname: 'rick',
age: 30
};
let foo = () => { console.log(this) }
let bar = function () { console.log(this) }
// call 对箭头函数无效
foo.call(obj); // window
bar.call(obj); // obj {...}
//案例2:筛选偶数
const arr = [1, 6, 9, 10, 100, 25]
// const result = arr.filter(function(item) {
// if(item % 2 === 0) {
// return true;
// } else {
// return false;
// }
// });
const result = arr.filter(item => item % 2 === 0);
console.log(result);
// 案例3:点击 div两秒后变成粉色
// ● 方案1:使用 _this 保存 div 下的 this,从而设置 div 的 style 属性
<style>
div {
width: 200px;
height: 200px;
background: #58a;
}
</style>
<div id="ad"></div>
<script>
let ad = document.getElementById('ad')
ad.addEventListener("click", function(){
//保存 this 的值
// let _this = this;
setTimeout(() => {
// console.log(this);
// _this.style.background = 'pink';
this.style.background = 'pink';
}, 2000);
})
</script>
//============================================================================
// ● 方案2:使用 => 箭头函数
// 箭头函数适合与 this 无关的回调. 定时器, 数组的方法回调
// 箭头函数不适合与 this 有关的回调. 事件回调, 对象的方法
div.addEventListener('click', function () {
setTimeout(() => {
console.log(thid); // <div id="ad" style="background: pink;"></div>
this.style.backgroundColor = 'pink';
}, 2000);
});
7、函数参数默认值设定
ES6 允许给函数参数设置默认值,当调用函数时不给实参,则使用参数默认值。
//具有默认值的形参,一般要靠后。
let add = (x, y, z=3) => x + y + z;
console.log(add(1, 2)); // 6
//可与解构赋值结合
function connect({ host = '127.0.0.1', uesername, password, port }) {
console.log(host); // 127.0.0.1
console.log(uesername);
console.log(password);
console.log(port);
}
connect({
// host: 'docs.mphy.top',要是在这里传了值,就用这个值,否则用第三行定义的默认值。
uesername: 'root',
password: 'root',
port: 3306
})
8、rest参数
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-E5BPtsah-1649332339006)(…/…/typroa/TyporaUserImg/image-20220313134949899.png)]
ES6 引入 rest 参数,用于获取函数的实参,用来代替 arguments,作用与 arguments 类似,将接收的参数序列转换为一个数组对象(arguments 是伪数组)。
语法格式:fn(a, b, …args),写在参数列表最后面。
应用场景:rest 参数非常适合不定个数参数函数的场景。
//案例1:求不定个数数字的和
let add = (...args) => {
let sum = args.reduce((pre, cur) => pre + cur, 0);
return sum;
}
console.log(add(1, 2, 3, 4, 5)); // 15
9、spread
扩展运算符
扩展运算符spread也是三个点…,它好比 rest 参数的逆运算,将一个数组、伪数组转为用逗号分隔的参数序列,对数组进行解包,扩展运算符也可以将对象解包。
可用在调用函数时,传递的实参,将一个数组转换为参数序列(与rest参数的区别,一个用在形参,一个实参)
//展开数组
function fn(a, b, c) {
console.log(arguments);
console.log(a + b + c);
}
let arr = ['red', 'green', 'blue'];
fn(...arr)
// [Arguments] { '0': 'red', '1': 'green', '2': 'blue' }
// redgreenblue
// 案例1:数组合并
let A = [1, 2, 3];
let B = [4, 5, 6];
let C = [...A, ...B];
console.log(C); // [1, 2, 3, 4, 5, 6]
// 案例2:数组克隆,这种数组克隆属于浅拷贝
let arr1 = ['a', 'b', 'c'];
let arr2 = [...arr1];
console.log(arr2); // ['a', 'b', 'c']
// 案例3:将伪数组转换为真实数组
const divs = document.querySelectorAll('div');
let divArr = [...divs];
console.log(divArr);
// 案例4:对象合并
let obj1 = {
a: 123
};
let obj2 = {
b: 456
};
let obj3 = {
c: 789
};
let obj = { ...obj1, ...obj2, ...obj3 };
console.log(obj);
// { a: 123, b: 456, c: 789 }
10.1、Symbol
JavaScript 的七种基本数据类型:
● 值类型(基本类型):string、number、boolean、undefined、null、symbol
● 引用数据类型:object(包括 array、function)
(USONB)
U undefined
S string
O object
N null 、 number
B boolean
ES6 引入了一种新的原始数据类型 Symbol,表示独一无二的值。
它是 JavaScript 语言的第七种数据类型,是一种类似于字符串的数据类型。
Symbol 的特点
● Symbol 的值是唯一的,用来解决命名冲突的问题
● Symbol 值不能与其他数据进行运算
● Symbol 定义的对象属性不能使用 for…in 循环遍历,但是可以使用 Reflect.ownKeys
来获取对象的所有键名。
Symbol 的创建
● 创建 Symbol()
创建
● 使用Symbol.for()
方法创建,名字相同的 Symbol
具有相同的实体。
● 输出 Symbol 变量的描述,使用 description
属性
// Symbol() 创建
let s = Symbol();
console.log(s, typeof s);
let s2 = Symbol('cess');
let s3 = Symbol('cess');
console.log(s2 === s3); // false
// Symbol.for 创建
let s4 = Symbol.for('cess');
let s5 = Symbol.for('cess');
console.log(s4 === s5); // true
// 不能与其他数据进行运算
let result = s + 100;
let result = s > 100;
let result = s + s;
let f = Symbol('测试一下');
console.log(f.description); // 测试一下
10.2 对象添加Symbol类型的属性
案例:安全的向对象中添加属性和方法。
分析:如果直接向对象中添加属性或方法,则原来对象中可能已经存在了同名属性或方法,会覆盖掉原来的。所以使用 Symbol 生成唯一的属性或方法名,可以更加安全的添加
// 这是一个 game 对象,假设我们不知道里面有什么属性和方法
const game = {
uname: '俄罗斯方块',
up: function () { },
down: function () { }
}
// 通过 Symbol 生成唯一的属性名,然后给 game 添加方法
let [up, down] = [Symbol('up'), Symbol('down')];
game[up] = function () {
console.log('up');
}
game[down] = function () {
console.log('down');
}
// 调用刚刚创建的方法
game[up]();
game[down]();
let youxi = {
name:"狼人杀",
[Symbol('say')]: function(){
console.log("我可以发言")
},
[Symbol('zibao')]: function(){
console.log('我可以自爆');
}
}
console.log(youxi)
11、Symbol的内置属性
12、迭代器
-
定义
迭代器Iterator是一种接口,为各种不同的数据结构提 供统一的访问机制。任何数据结构只要部署 Iterator 接口(在 js 中接口就是对象的一个属性),就可以完成遍历操作。
● ES6 创造了一种新的遍历命令for…of循环,Iterator 接口主要供 for…of 消费
○ for…in 取的是索引,for…of 取的是 value
● 原生具备 iterator 接口的数据(可用 for of 遍历)
○Array
○Arguments
○Set
○Map
○String
○TypedArray
○NodeList
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MbRCO07Y-1649332339007)(…/…/typroa/TyporaUserImg/image-20220315173418439.png)]
1、创建一个指针对象,指向当前数据结构的起始位置
2、第一次调用对象的 next 方法,指针自动指向数据结构的第一个成员
3、接下来不断调用 next 方法,指针一直往后移动,直到指向最后一个成员
4、每调用 next 方法返回一个包含 value 和 done 属性的对象
应用场景:需要自定义遍历数据的时候,要想到迭代器。
-
自定义遍历数据
const banji = { name: "终极一班", stus: ['xiaoming', 'xiaoning', 'xiaotian', 'knight'], [Symbol.iterator]() { let index = 0; // 索引变量 let _this = this; return { next: function () { if (index < _this.stus.length) { const result = { value: _this.stus[index], done: false }; index++; // 下标自增 return result; // 返回结果 } else { return {value: undefined, done: true}; } } }; } } // 遍历这个对象 for (let v of banji) { console.log(v); }
12、Generator生成器函数
1、 生成器函数的声明和调用
生成器函数是 ES6 提供的一种 异步编程解决方案,语法行为与传统采用纯回调函数完全不同
一般函数从开始运行到它结束之前,不会被任何事情打断。而生成器可以在执行当中暂停自身,可以立即恢复执行,也可以过一段时间之后恢复执行,所以生成器它不能像普通函数那样保证运行到完毕
生成器在每次 暂停/恢复 都提供了一个双向传递信息的功能,生成器可以返回一个值,恢复它的控制代码也可以接收一个值。
1、使用` function * generator()` 和` yield `可以声明一个生成器函数,* 的位置随意。
2、生成器函数返回的结果是迭代器对象,调用迭代器对象的 next() 方法可以得到 yield 语句后的值。
3、每一个 yield 相当于函数的暂停标记,类似 return 要返回值,但不退出函数,每调用一次 next(),生成器函数就往下执行一段
4、next 方法可以传递实参,作为 yield 语句的返回值
如下生成器函数中,3 个 yield 语句将函数内部分成了 4 段
// 生成器其实就是一个特殊的函数
// 步编程 纯回调函数 node fs ajax mongodb
// yield 暂停标记
function * gen(){
// console.log(111);
yield '一只没有耳朵';
// console.log(222);
yield '一只没有尾部';
// console.log(333);
yield '真奇怪';
// console.log(444);
}
let iterator = gen();
console.log(iterator.next()); // 每调一次,执行一段,并返回yield后面的值
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
// 遍历
for(let v of gen())
console.log(v);
}
2、 生成器函数的参数传递
function * gen(arg){
console.log(arg);
let one = yield 111;
console.log(one);
let two = yield 222;
console.log(two);
let three = yield 333;
console.log(three);
}
let iter = generator('AAA'); // 传给生成器第 1 段
console.log(iter.next());
console.log(iter.next('BBB'));
console.log(iter.next('CCC'));
console.log(iter.next('DDD'));
// 结果
AAA
Object{value: 111, done: false}
BBB
Object{value: 222, done: false}
CCC
Object{value: 333, done: false}
DDD
Object{value: undefined, done: true}
笔记:https://www.yuque.com/cessstudy/kak11d/cbd3so#799c541b
3、生成器函数案例(回调地狱)
13. Promise
1 Promise 的定义和使用
Promise
是 ES6 引入的异步编程的新解决方案,语法上 Promise 是一个构造函数,用来封装异步操作并可以获取其成功或失败的结果。
一个 Promise 必然处于以下几种状态之一:
● 待定 pending:初始状态,既没有被兑现,也没有被拒绝
● 已兑现 fulfilled:意味着操作成功完成
● 已拒绝 rejected:意味着操作失败
Promise 的使用:
● Promise 构造函数new Promise((resolve, reject) => {})
● Promise.prototype.then()方法
● Promise.prototype.catch()方法
let p = new Promise(function (resolve, reject) {
// 使用 setTimeout 模拟请求数据库数据操作
setTimeout(function () {
let isRight = true; // 这个异步请求数据库数据操作是否正确返回数据
if (isRight) {
let data = '数据库中的数据';
resolve(data); // 设置 Promise 对象的状态为操作成功
} else {
let err = '数据读取失败!'
reject(err); // 设置 Promise 对象的状态为操作失败
}
}, 1000);
});
p.then(function (value) {
console.log(value);
}, function (reason) {
console.error(reason);
})
Promise 的使用:
● Promise 构造函数new Promise((resolve, reject) => {})
● Promise.prototype.then()方法
● Promise.prototype.catch()方法
let p = new Promise(function (resolve, reject) {
// 使用 setTimeout 模拟请求数据库数据操作
setTimeout(function () {
let isRight = true; // 这个异步请求数据库数据操作是否正确返回数据
if (isRight) {
let data = '数据库中的数据';
resolve(data); // 设置 Promise 对象的状态为操作成功
} else {
let err = '数据读取失败!'
reject(err); // 设置 Promise 对象的状态为操作失败
}
}, 1000);
});
p.then(function (value) {
console.log(value);
}, function (reason) {
console.error(reason);
})