简化对象写法
ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。
这样的书写更加简洁
let name = '你猜吧';
let slogon = '永远追求行业更高标准';
let improve = function () {
console.log('可以提高你的技能');
}
// 属性和方法简写
let atguigu = {
name,
slogon,
improve,
change() {
console.log('可以改变你')
}
};
箭头函数
ES6 允许使用「箭头」(=>)定义函数。
let fn = (arg1, arg2, arg3) => {
return arg1 + arg2 + arg3;
}
箭头函数的注意点:
- 如果形参只有一个,则小括号可以省略
- 函数体如果只有一条语句,则花括号可以省略,函数的返回值为该条语句的执行结果
- 箭头函数 this 指向声明时所在作用域下 this 的值
- 箭头函数不能作为构造函数实例化
- 不能使用 arguments
- this 是静态的. this 始终指向函数声明时所在作用域下的 this 的值
function getName(){
console.log(this.name);
}
let getName2 = () => {
console.log(this.name);
}
//设置 window 对象的 name 属性
window.name = '你来猜';
const school = {
name: "any"
}
//直接调用
getName(); // 你来猜
getName2();// 你来猜
//call 方法调用
getName.call(school); //any
getName2.call(school);//你来猜
- 不能作为构造实例化对象
let Person = (name, age) => {
this.name = name;
this.age = age;
}
let me = new Person('xiao',30);
console.log(me); // Person is not a constructor
- 不能使用 arguments 变量
let fn = () => {
console.log(arguments);
//arguments is not defined
}
fn(1,2,3);
- 箭头函数的简写
-1) 省略小括号, 当形参有且只有一个的时候
- 箭头函数的简写
let add = n => {
return n + n;
}
console.log(add(9)); //18
-2) 省略花括号, 当代码体只有一条语句的时候, 此时 return 必须省略
而且语句的执行结果就是函数的返回值
let pow = n => n * n;
console.log(pow(8)); //64
箭头函数实践
- 需求-1 点击 div 2s 后颜色变成『粉色』
let ad = document.getElementById('ad');
//绑定事件
ad.addEventListener("click", function(){
//保存 this 的值
// let _this = this;
//定时器
setTimeout(() => {
//修改背景颜色 this
// console.log(this);
// _this.style.background = 'pink';
this.style.background = 'pink';
}, 2000);
});
- 需求-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);
总结
- 箭头函数适合与 this 无关的回调. 定时器, 数组的方法回调
- 箭头函数不适合与 this 有关的回调. 事件回调, 对象的方法
变量的解构赋值
ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称
为解构赋值.
- 数组的解构赋值
const arr = ['张学友', '刘德华', '黎明', '郭富城'];
let [zhang, liu, li, guo] = arr;
- 对象的解构赋值
const lin = {
name: '林志颖',
tags: ['车手', '歌手', '小旋风', '演员']
};
let {name, tags} = lin;
- 复杂解构
let wangfei = {
name: '王菲',
age: 18,
songs: ['红豆', '流年', '暧昧', '传奇'],
history: [
{name: '窦唯'},
{name: '李亚鹏'},
{name: '谢霆锋'}
]
};
let {songs: [one, two, three], history: [first, second, third]} =
wangfei;
es6允许参数有默认值
- 形参初始值 具有默认值的参数, 一般位置要靠后
function add(a,b,c=10) {
return a + b + c;
}
let result = add(1,2);
console.log(result);
- 与解构赋值结合
function connect({host="127.0.0.1", username,password, port}){
console.log(host)
console.log(username)
console.log(password)
console.log(port)
}
connect({
host: 'atguigu.com',
username: 'root',
password: 'root',
port: 3306
})
rest 参数
...
- ES6 引入 rest 参数,用于获取函数的实参,用来代替 arguments
- ES5 获取实参的方式(对象)
function date() {
console.log(arguments);
}
date('白芷','阿娇','思慧'); //3
- es6使用...(数组)
function date(...args){
console.log(args);// filter some every map
}
date('阿娇','柏芝','思慧');
- rest 参数必须要放到参数最后
function fn(a,b,...args){
console.log(a);
console.log(b);
console.log(args);
}
fn(1,2,3,4,5,6);
spread扩展运算符
扩展运算符(spread)也是三个点(...)。它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列,对数组进行解包。
// 『...』 扩展运算符能将『数组』转换为逗号分隔的『参数序列』
//声明一个数组 ...
const tfboys = ['易烊千玺','王源','王俊凯'];
// => '易烊千玺','王源','王俊凯'
// 声明一个函数
function chunwan(){
console.log(arguments);
}
chunwan(...tfboys);// chunwan('易烊千玺','王源','王俊凯')
扩展运算符的应用
- 数组的合并
const kuaizi = ['王太利','肖央'];
const fenghuang = ['曾毅','玲花'];
// const zuixuanxiaopingguo = kuaizi.concat(fenghuang);
const zuixuanxiaopingguo = [...kuaizi, ...fenghuang];
console.log(zuixuanxiaopingguo); //["王太利", "肖央", "曾毅", "玲花"]
- 数组的克隆(浅拷贝)
const arr1 = ['E','G','M'];
const arr2 = [...arr1];// ['E','G','M']
console.log(arr2);
- 将伪数组转为真正的数组
const divs = document.querySelectorAll('div');
const divArr = [...divs];
console.log(divArr);// arguments
// [div, div, div]
Symbol
ES6 引入了一种新的原始数据类型 Symbol,表示独一无二的值。它是
JavaScript 语言的第七种数据类型,是一种类似于字符串的数据类型。
Symbol 特点
- Symbol 的值是唯一的,用来解决命名冲突的问题
- Symbol 值不能与其他数据进行运算
- Symbol 定义的对象属性不能使用 for…in 循环遍历,但是可以使用
Reflect.ownKeys 来获取对象的所有键名
- 创建Symbol
let s = Symbol();
console.log(s, typeof s); //Symbol() "symbol"
- 添加标识的 Symbol
let s2 = Symbol('222');
let s3 = Symbol('222');
console.log(s2 === s3) // false
- 使用 Symbol for 定义
let s4 = Symbol.for('333');
let s5 = Symbol.for('333');
console.log(s4 === s5) // true
Symbol创建对象属性
<script>
//向对象中添加方法 up down
let game = {
name:'俄罗斯方块',
up: function(){},
down: function(){}
};
//声明一个对象
// let methods = {
// up: Symbol(),
// down: Symbol()
// };
// game[methods.up] = function(){
// console.log("我可以改变形状");
// }
// game[methods.down] = function(){
// console.log("我可以快速下降!!");
// }
// console.log(game);
//
let youxi = {
name:"狼人杀",
[Symbol('say')]: function(){
console.log("我可以发言")
},
[Symbol('zibao')]: function(){
console.log('我可以自爆');
}
}
console.log(youxi)
</script>
image.png
Symbol 内置值
除了定义自己使用的 Symbol 值以外,ES6 还提供了 11 个内置的 Symbol 值,指向语言内部使用的方法。可以称这些方法为魔术方法,因为它们会在特定的场
image.png
迭代器
遍历器(Iterator)就是一种机制。它是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署 Iterator 接口,就可以完成遍历操作。
- ES6 创造了一种新的遍历命令 for...of 循环,Iterator 接口主要供 for...of 消费
- 原生具备 iterator 接口的数据(可用 for of 遍历)
a) Array
b) Arguments
c) Set
d) Map
e) String
f) TypedArray
g) NodeList - 工作原理
a) 创建一个指针对象,指向当前数据结构的起始位置
b) 第一次调用对象的 next 方法,指针自动指向数据结构的第一个成员
c) 接下来不断调用 next 方法,指针一直往后移动,直到指向最后一个成员
d) 每调用 next 方法返回一个包含 value 和 done 属性的对象
注: 需要自定义遍历数据的时候,要想到迭代器
//声明一个数组
const xiyou = ['唐僧','孙悟空','猪八戒','沙僧'];
//使用 for...of 遍历数组
// for(let v of xiyou){
// console.log(v);
// }
let iterator = xiyou[Symbol.iterator]();
//调用对象的next方法
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
image.png
迭代器自定义遍历对象
<script>
//声明一个对象
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);
}
</script>
生成器
生成器函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同
代码说明:
- "*"的位置没有限制
- 生成器函数返回的结果是迭代器对象,调用迭代器对象的 next 方法可以得到
yield 语句后的值 - yield 相当于函数的暂停标记,也可以认为是函数的分隔符,每调用一次 next
方法,执行一段代码 - next 方法可以传递实参,作为 yield 语句的返回值
生成器函数:
//生成器其实就是一个特殊的函数
//异步编程 纯回调函数 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()); // 一只没有耳朵
console.log(iterator.next()); // 一只没有尾部
console.log(iterator.next()); // 真奇怪
console.log(iterator.next()); // undefined
//遍历
// for(let v of gen()){
// console.log(v);
// }
生成器函数参数
function * gen(arg){
console.log(arg)
let one = yield 111;
console.log(one);
let two = yield 222;
console.log(two)
let tree = yield 333;
console.log(tree)
}
//执行获取迭代器对象
let iterator = gen('AAA');
console.log(iterator.next());
//next方法可以传入实参
console.log(iterator.next('BBB'));
console.log(iterator.next('CCC'));
console.log(iterator.next('DDD'));
image.png
实例生成器函数解决回调地狱
function one(){
setTimeout(()=>{
console.log(111);
iterator.next(); //111
},1000)
}
function two(){
setTimeout(()=>{
console.log(222);
iterator.next(); //222
},2000)
}
function three(){
setTimeout(()=>{
console.log(333);
iterator.next(); //333
},3000)
}
function * gen(){
yield one();
yield two();
yield three();
}
//调用生成器函数
let iterator = gen();
iterator.next();
模拟同步获取数据
//模拟获取 用户数据 订单数据 商品数据
function getUsers(){
setTimeout(()=>{
let data = '用户数据';
//调用 next 方法, 并且将数据传入
iterator.next(data);
}, 1000);
}
function getOrders(){
setTimeout(()=>{
let data = '订单数据';
iterator.next(data);
}, 1000)
}
function getGoods(){
setTimeout(()=>{
let data = '商品数据';
iterator.next(data);
}, 1000)
}
function * gen(){
let users = yield getUsers();
console.log(users )
let orders = yield getOrders();
console.log(orders)
let goods = yield getGoods();
console.log(goods)
}
//调用生成器函数
let iterator = gen();
iterator.next();
网友评论