es6-11新特性
四、扩展运算符(展开语法)
- 将类数组或可遍历对象转换为真正的数组
- 为什么要将伪数组转变为真正的数组?这样可以使用数组的一些方法
let oDivs = document.getElementsByTagName('div');
oDivs = [...oDivs];
五、Array的扩展方法
1、构造函数方法:Array.from()
1.将类数组或可遍历对象转变为真正的数组
//伪数组
var arraylike = {
"0": "张三",
"1": "李四",
"2": "王五",
"length": 3
}
var arr = Array.from(arraylike);
console.log(arr)
2.方法还可以接受第二个参数,作用类似于数组的map方法,用来对每个元素进行处理,将处理后的值放入返回的数组
var arr5 = {
"0": "5",
"1": "6",
length: 2
}
var ary = Array.from(arr5, item => item * 5);
console.log(ary);//[25,30]
2、实例方法find()
用于找出第一个符合条件的数组成员,如果没有找到返回undefined
var ary = [{ id: 5, name: "张三" }, { id: 6, name: "李四" }];
let target = ary.find(item => item.id === 6);
console.log(target);//{ id: 6, name: "李四" }
3、实例方法findIndex()
用于找出第一个符合条件的数组成员的位置,如果没有找到返回-1
let ary = [5, 6, 50, 60, 70];
const target = ary.findIndex(item => item > 50);
console.log(target);//3
4、实例方法includes()
表示某个数组是否包含给定的值,返回布尔值
let ary = ["a", "b", "c",];
const target = ary.includes('a');
console.log(target);//true
const target6 = ary.includes('e');
console.log(target6);//false
六、String的扩展方法
1、模板字符串
es6新增的创建字符串的方式,使用反引号定义
let name=`这是一个模板字符串`;
console.log(name)//这是一个模板字符串
-
模板字符串可以解析变量
let name = "张三"; let sayHello = `hello,我的名字叫${name}`; console.log(sayHello);
-
模板字符串中可以换行
let person = { name: "张三", age: 50 } let result = ` <div> <span>${person.name}</span> <span>${person.age}</span> </div> `
-
在模板字符串中可以调用函数
const fn = () => "我是fn函数"; let html = `我是模板字符串${fn()}`; console.log(html);//我是模板字符串我是fn函数
2、实例方法:startsWith()和endsWith()
-
startsWith():表示参数字符串是否在原字符串的头部,返回布尔值
-
endsWith():表示参数字符串是否在原字符串的尾部,返回布尔值
let str ='Hello world!'; str.startsWith('Hello') //true str.endsWith('!')//true
3、实例方法:repeat()
repeat方法表示将原字符串重复n次,返回一个新字符串
'x'.repeat(3) //'xxx'
'hello'.repeat(2) //'hellohello'
七、Set数据结构
es6提供了新的数据结构Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。
-
Set本身是一个构造函数,用来生成Set数据结构
const s = new Set();
-
Set函数可以接受一个数组作为参数,用来初始化
```
const set = new Set([1,2,3,4,4]);
```
应用利用set做数组去重
const s3 = new Set(['a', 'b', 'a', 'b']);
console.log(s3.size) //2
const ary = [...s3];
console.log(ary)//["a", "b"]
实例方法
- add(value):添加某个值,返回Set结构本身
- delete(value):删除某个值,返回一个布尔值,表示删除是否成功
- has(value):返回一个布尔值,表示该值是否为set的成员
- clear();清除所有成员,没有返回值
const s4 = new Set();
//向set结构中添加值,使用add方法
s4.add('a').add('b');
console.log(s4.size); //2
//从set结构中删除值,用到的方法是delete
const r1 = s4.delete('b');
console.log(s4.size); //1
console.log(r1); //true
const r2 = s4.delete('c');
console.log(s4.size);//1
console.log(r2);//false
//判断某一个值是否是set数据结构中的成员 使用has
const r3 = s4.has('a');
console.log(r3); //true
//清空set数据结构中的值,使用clear方法
s4.clear();
console.log(s4.size); //0
遍历
Set结构的实例与数组一样,也拥有forEach方法,用于对每个成员执行某种操作,没有返回值
const s5 = new Set(['a', 'b', 'c']);
s5.forEach(value => {
console.log(value) //a b c
})
https://blog.csdn.net/m0_61490399/article/details/125407295?csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22125407295%22%2C%22source%22%3A%22m0_61490399%22%7D&ctrtid=l1iEE
一、ECMAScript6 新特性
1、let关键字
let a;
let b,c,d;
let e=600;
let f=90,g="ddd",h=[];
-
let关键字用来声明变量,let与var对比
-
变量不能重复声明
let star = '张子枫'; let star = "ddd";//重复声明会报错
-
块级作用域(只在代码块里有效)
{ let girl = '张子枫'; var girls = '张子枫'; } console.log(girl);//girl is not defined console.log(girls);//张子枫
-
不存在变量提升(代码在执行之前会提前收集变量,对于var声明的变量会赋初始值undefined)
也即不允许在变量声明之前使用变量
console.log(songs); let song = "hhhh";// Uncaught ReferenceError: Cannot access 'song' before initialization var songs = "hhhh";//undefined
-
不影响作用域链
-
{
let school = "哈哈哈";
function fn() {
console.log(school)
}
fn();
}
- 应用
- 解决 作用域解决点击 but[i]\this.的问题
let经典案例
<div class="container">
<h2 class="">点击切换颜色</h2>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
<script type="text/javascript">
//获取div元素对象
let items = document.getElementsByClassName('item');
//遍历并绑定事件
// for (var i = 0; i < items.length; i++) {
// items[i].onclick = function () {
// items[i].style.background = 'pink';
// }
// }
//用var声明会报错 Cannot read property 'style' of undefined
// at HTMLDivElement.items.< computed >.onclick
//相当于以下步骤
// {
// var i = 0;
// }
// {
// var i = 1;
// }
// {
// var i = 2;
// }
console.log(window.i)//3 因为div下标最大为2,所以会报错
//方法一、let声明变量
// for (let i = 0; i < items.length; i++) {
// items[i].onclick = function () {
// items[i].style.background = 'pink';
// }
// }
// {
// let i = 0;
// items[i].onclick = function () {
// items[i].style.background = 'pink';
// }
// }
// {
// let i = 1;
// }
// {
// let i = 2;
// }
//方法二、也可利用闭包的方式得到当前的索引号
//闭包(closure)//指有权访问另一个函数作用域中变量的函数
// for (var i = 0; i < items.length; i++) {
// //利用for循环创建4个立即执行函数
//立即执行函数也称为小闭包,因为立即执行函数里面的任何一个函数都可以使用它的i变量
// (function (i) {
// console.log(i);
// items[i].onclick = function () {
// items[i].style.background = 'pink';
// }
// })(i)
// }
//方法三、利用动态添加属性的方式
for (let i = 0; i < items.length; i++) {
items[i].index = i;
items[i].onclick = function () {
items[this.index].style.background = 'pink';
}
}
2. const 关键字
-
const 关键字用来声明变量
-
声明必须赋初始值
-
标识符一般为大写(潜规则)
-
值不允许修改
-
也不允许重复声明
-
块级作用域
-
对于数组和对象的元素修改,不算做对常量的修改,不会报错
//const 定义的引用数据类型,保存的是地址,地址本身不能修改,但是它所指向的那片堆内存是可以修改的 const TEAM=['UZI','MCLG','MIng','dd']; TEAM.push('XINMEI');//不会报错
-
3. 变量的解构赋值
- ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为 解构赋值
- 数组的解构赋值:
javascript
const arr = [‘red’, ‘green’, ‘blue’];
let [r, g, b] = arr; - 对象的解构赋值:
let obj = {
name: 'xiansheng',
age: 23,
obj1: function () {
console.log('hello');
},
}
let {name, age, obj1} = obj;
console.log(name,age,obj1())
应用场景:频繁使用对象方法、数组元素,就可以使用解构赋值形式。
4、模板字符串
es6新增的创建字符串的方式,使用反引号定义
let name=`这是一个模板字符串`;
console.log(name)//这是一个模板字符串
-
模板字符串可以解析变量
let name = "张三"; let sayHello = `hello,我的名字叫${name}`; console.log(sayHello);
-
模板字符串中可以换行
let person = { name: "张三", age: 50 } let result = ` <div> <span>${person.name}</span> <span>${person.age}</span> </div> `
-
在模板字符串中可以调用函数
const fn = () => "我是fn函数"; let html = `我是模板字符串${fn()}`; console.log(html);//我是模板字符串我是fn函数
5. 简化对象写法
-
ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。这样的书写更加简洁。
let name= 'xiansheng'; let age = 35; let obj1= function () { console.log('obj1'); } //简写 const obj = { name, age, obj1 }
-
应用场景:对象简写形式简化了代码,所以以后用简写就对了。
6. 箭头函数
- 简写一:
fun(a,b){console.log(a+b)} =》 (a,b)=>{console.log(a,b)}
- 简写二:
fun(a){return a} =》 当只有一个参数且只有一个返回值的时候可以这样; a=>a;
-
特点
-
this是静态的,this始终指向函数声明时所在作用域下的this的值
function fn6() { console.log(this); return () => { console.log(this.name);//张三 } } const obj = { name: "张三" }; const resFn = fn6.call(obj); resFn();
//this是静态的,this始终指向函数声明时所在作用域下的this的值
window.name = ‘是是是’;
const user = {
name: ‘hhh’
}
function getName() {
console.log(this.name);
}
let getName2 = () => {
console.log(this.name);
}
function getName3() {return () => { console.log(this.name);//张三 } } //设置window对象的name属性 //直接调用 getName();// '是是是' getName2();// '是是是' console.log("jjjjjjjjjjjjjjjj") getName3.call(user);// 'hhh' //call方法调用 getName.call(user);// 'hhh' getName2.call(user);// '是是是'
-
不能使用call,apply改变this的指向
-
没有arguments
-
不能用构造函数去实例对象
箭头函数案例, 1、点击div 2s后颜色变成粉色
-
//需求 点击div 2s后颜色变成粉色
let ad = document.getElementById('ad');
ad.addEventListener("click", function () {
//方法一,保存this的值
// let that = this;
// setTimeout(function () {
// that.style.background = 'pink';
// }, 2000)
//方法二,使用箭头函数
setTimeout(() => {
this.style.background = 'pink';
}, 2000)
})
2、返回偶数
const arr = [5,6,9,50,60];
const result = arr.filter(item=>item%2===0);
console.log(result)//[6,50,60]
箭头函数适合与this无关的回调,定时器,数组的方法回调
箭头函数不适合与this有关的回调。事件回调,对象的方法
7. 函数参数默认值设定
-
ES6 允许给函数参数设置默认值,当调用函数时不给实参,则使用参数默认值。
-
具有默认值的形参,一般要靠后。
(x, y, z=3) =>{console.log(x + y + z) }; console.log(add(1, 2)); // 6 * 可与解构赋值结合: ```javascript function connect({ host = '127.0.0.1', uesername, password, port }) { console.log(host); // 127.0.0.1 console.log(uesername); //root console.log(password); //root console.log(port); //3306 } connect({ // host: 'docs.mphy.top', uesername: 'root', password: 'root', port: 3306 })
8. rest 参数
-
ES6 引入 rest 参数,用于获取函数的实参,用来代替 arguments,作用与 arguments 类似。将接收的参数序列转换为一个数组对象。
-
用在函数形参中,语法格式:Fun(a, b, …args),写在参数列表最后面。
let Fun= (a, b, ...arr) => { console.log(a);//1 console.log(b);//2 console.log(arr);//[3,4,5] }; Fun(1,2,3,4,5); * 案例 ```javascript let add = (...arr) => { let sum = arr.reduce((pre, cur) => { return pre + cur }); return sum; } console.log(add(1, 2, 3, 4, 5)); // 15
应用场景:rest 参数非常适合不定个数参数函数的场景
9. spread 扩展运算符
-
扩展运算符(spread)也是三个点(…)。它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列,对数组进行解包。可用在调用函数时,传递的实参,将一个数组转换为参数序列。
-
展开数组:
function fn(a, b, c) { console.log(arguments); //Arguments(3) [1, 2, 3, Function, Function] console.log(a + b + c); //6 } let arr = [1,2,3]; fn(...arr) * 数组合并: ```javascript let A = [1, 2, 3]; let B = [4, 5, 6]; let C = [...A, ...B]; console.log(C); // [1, 2, 3, 4, 5, 6] * 浅克隆数组: ```javascript let arr1 = ['a', 'b', 'c']; let arr2 = [...arr1]; console.log(arr2); // ['a', 'b', 'c'] * 将伪数组转换为真实数组 ```javascript let div= document.querySelectorAll('div'); let divArr = [...div]; console.log(divArr); * 对象合并 ```javascript // 合并对象 let obj1 = { a: 123 }; let obj2 = { b: 456 }; let obj = { ...obj1, ...obj2}; console.log(obj); //{ a: 123, b: 456}
10. Symbol
10.1 Symbol 基本介绍与使用
- ES6 引入了一种新的原始数据类型 Symbol,表示独一无二的值。它是 JavaScript 语言的第七种数据类型,是一种类似于字符串的数据类型。
- JavaScript 的七种基本数据类型:
- 基本数值类型:string、number、boolean、undefined、null、symbol
- 引用数值类型:Object(包括了Array、Function)
-
Symbol 的特点:
- Symbol 的值是唯一的,用来解决命名冲突的问题
- Symbol 值不能与其他数据进行运算
- Symbol 定义的对象属性不能使用 for…in 循环遍历,但是可以使用 Reflect.ownKeys 来获取对象的所有键名
-
Symbol 的创建:
-
创建一个 Symbol:
let s1 = Symbol(); console.log(s1, typeof s1); // Symbol() symbol
2.添加具有标识的 Symbol:
let s2 = Symbol('1');
let s2_1 = Symbol('1');
console.log(s2 === s2_1); // false Symbol 都是独一无二的
使用 Symbol.for() 方法创建,名字相同的 Symbol 具有相同的实体。
3、使用 Symbol.for() 方法创建,名字相同的 Symbol 具有相同的实体。
let s3 = Symbol.for('apple');
let s3_1 = Symbol.for('apple');
console.log(s3 === s3_1); // true
4.输出 Symbol 变量的描述,使用 description 属性
let s4 = Symbol('测试');
console.log(s4.description); // 测试
10.2 对象添加 Symbol 类型的属性
- ES6 引入 rest 参
- 案例:安全的向对象中添加属性和方法。
- 分析:如果直接向对象中添加属性或方法,则原来对象中可能已经存在了同名属性或方法,会覆盖掉原来的。所以使用 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]();
10.3 Symbol 内置值
- 除了定义自己使用的 Symbol 值以外,ES6 还提供了11 个内置的 Symbol 值,指向语言内部使用的方法。可以称这些方法为魔术方法,因为它们会在特定的场景下自动执行。
-
方法 | 描述 |
---|---|
Symbol.hasInstance | 当其他对象使用 instanceof 运算符,判断是否为该对象的实例时,会调用这个方法 |
Symbol.isConcatSpreadabl | 对象的 Symbol.isConcatSpreadable 属性等于的是一个布尔值,表示该对象用于Array.prototype.concat() 时,是否可以展开 |
Symbol.species | 创建衍生对象时,会使用该属性 |
Symbol.match | 当执行 str.match(myObject) 时,如果该属性存在,会调用它,返回该方法的返回值。 |
Symbol.replace | 当该对象被 str.replace(myObject) 方法调用时,会返回该方法的返回值。 |
Symbol.search | 当该对象被 str.search(myObject) 方法调用时,会返回该方法的返回值。 |
Symbol.split | 当该对象被 str.split(myObject) 方法调用时,会返回该方法的返回值。 |
Symbol.iterator | 对象进行 for…of 循环时,会调用 Symbol.iterator 方法,返回该对象的默认遍历器 |
Symbol.toPrimitive | 该对象被转为原始类型的值时,会调用这个方法,返回该对象对应的原始类型值。 |
Symbol. toStringTag | 在该对象上面调用 toString() 方法时,返回该方法的返回值 |
Symbol. unscopables | 该对象指定了使用 with 关键字时,哪些属性会被 with 环境排除。 |
11. Iterator迭代器
11.1定义
-
说明:(按我们自己的意愿去遍历对象里面的数据)遍历器(Iterator)就是一种机制。它是一种接口,为各种不同的数据结构提 供统一的访问机制。任何数据结构只要部署 Iterator 接口(指对象里面的属性,属性名是Symbol.iterator),就可以完成遍历操作。
-
ES6 创造了一种新的遍历命令 for…of 循环,Iterator 接口主要供 for…of 消费。
-
原生具备 iterator 接口的数据(可用for of 遍历)
Array
Arguments
Set
Map
String
TypedArray
NodeList -
案例:使用 next() 方法遍历原生自带 iterator 接口的数据:
let obj={ name:"先生", arr:[1,1,5,4,4,5,88,88,89], [Symbol.iterator]:function (){ let _this=this let index=0 return{ next:function (){ if(index<_this.arr.length){ let data={value:_this.arr[index],done:false} index++ return data }else{ return{value: undefined,done: true} } } } } } for (const objElement of obj) { console.log(objElement) }
const arr = ["张子枫", '彭昱畅', '黄磊', "张艺兴", "何炅"];
const arr2 = [{ "id": "1", name: "张子枫" }, { "id": "2", name: "彭昱畅" }];
for (let v of arr2) {
console.log(v);//{id: "1", name: "张子枫"}{id: "2", name: "彭昱畅"}
}
for (let v in arr2) {
console.log(v);//0 1
}
for (let v of arr) {
console.log(v);//张子枫 彭昱畅...
}
for (let v in arr) {
console.log(v); //0 1 2 3 4
}
//for in 推荐遍历对象,也可遍历数组,for of只能遍历数组
// for of 是value, for in 是key
let iterator = arr[Symbol.iterator]();
console.log(arr);
//调用对象的next方法
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
11.2 工作原理
-
创建一个指针对象,指向当前数据结构的起始位置
-
第一次调用对象的 next 方法,指针自动指向数据结构的第一个成员
-
接下来不断调用 next 方法,指针一直往后移动,直到指向最后一个成员
-
每调用 next 方法返回一个包含 value 和 done 属性的对象
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uvbX23pK-1667266916518)(C:\Users\zxm\AppData\Local\Temp\1667218580982.png)]
11.3应用场景:需要自定义遍历数据的时候,要想到迭代器
//声明一个对象
const life = {
name: "向往的生活",
members: ["张子枫", '彭昱畅', '黄磊', "张艺兴", "何炅"],
[Symbol.iterator]: function () {
//声明变量
let index = 0;
let that = this;
return {
// next: function () {
// if (index < that.members.length) {
// const result = { value: that.members[index], done: false };
// //下班自增
// index++;
// return result;
// } else {
// return { value: undefined, done: true }
// }
// }
//或使用箭头函数
next: () => {
if (index < this.members.length) {
const result = { value: this.members[index], done: false };
//下班自增
index++;
return result;
} else {
return { value: undefined, done: true }
}
}
}
}
}
//需求遍历对象,for of 返回数组的成员。为啥,避免对成员直接操作
for (let l of life) {
console.log(l)
}
12. Generator 生成器函数
12.1 生成器函数的声明和调用
- 生成器函数是 ES6 提供的一种 异步编程解决方案,语法行为与传统函数完全不同
- 使用 function * gen() 和 yield 可以声明一个生成器函数。生成器函数返回的结果是迭代器对象,调用迭代器对象的 next 方法可以得到 yield 语句后的值。
- *的位置没有限制
- 每一个 yield 相当于函数的暂停标记,也可以认为是一个分隔符,每调用一次 next(),生成器函数就往下执行一段。
- next 方法可以传递实参,作为 yield 语句的返回值
案例
//生成器其实就是一个特殊的函数
//作用:异步编程 纯回调函数 node fs ajax mongodb
//yield 相当于函数代码的分隔符
function* gen() {
// console.log("hhhh");
yield '一直下雨';
// console.log("hhhh789");
yield '一直秦天'
console.log("hhhh7");
yield '一直feng'
}
let iterator = gen();
iterator.next();//hhhh
iterator.next();//hhhh789
iterator.next();//hhhh7
console.log(iterator);
//遍历
for (let v of gen()) {
console.log(v) //一直下雨 一直秦天 一直feng
}
12.2 生成器函数参数传递
//生成器的参数传递
function* gen8(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 itera = gen8('AAA');
console.log(itera.next());
//next方法可以传入实参,作为上一个yield的返回结果
console.log(itera.next("BBB"));
console.log(itera.next("CCC"));
console.log(itera.next("DDD"));
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dKMhXaWv-1667266916519)(C:\Users\zxm\AppData\Local\Temp\1667222534518.png)]
12.3生成器函数实例
//异步编程常见案例 文件操作 网络操作(ajax,request) 数据库操作
//案例需求:1s 后控制台输出111,2s 后控制台输出222,3s后输出333
//方法一实现,setTimeout 会形成回调地狱
setTimeout(() => {
console.log(111)
setTimeout(() => {
console.log(222)
setTimeout(() => {
console.log(333)
}, 3000)
}, 2000)
}, 1000)
//方案二实现,生成器,可解决回调地狱
function one() {
setTimeout(() => {
console.log(111)
iterat.next();
}, 1000)
}
function two() {
setTimeout(() => {
console.log(222)
iterat.next();
}, 2000)
}
function three() {
setTimeout(() => {
console.log(333)
iterat.next();
}, 3000)
}
function* fens() {
yield one();
yield two();
yield three();
}
let iterat = fens();
iterat.next();
//案例二、模拟获取用户数据,再获取订单数据、再获取商品数据
function getUsers() {
setTimeout(() => {
let data = "用户数据"
it.next(data);
}, 1000)
}
function getOrders() {
setTimeout(() => {
let data = "订单数据"
it.next(data);
}, 1000)
}
function getGoods() {
setTimeout(() => {
let data = "商品数据"
it.next(data);
}, 1000)
}
function* gens() {
let users = yield getUsers();
console.log(users)
let orders = yield getOrders();
console.log(orders)
let goods = yield getGoods();
console.log(goods)
}
//调用生成器函数
let it = gens();
it.next();
13、promise
13.1promise介绍与基本使用
Promise是es6引入的异步编程的新解决方案(解决异步编程的回调地狱问题)。语法上Promise是一个构造函数,用来封装异步操作并可以取得其成功和失败的结果
d three();
}
let iterat = fens();
iterat.next();
//案例二、模拟获取用户数据,再获取订单数据、再获取商品数据
function getUsers() {
setTimeout(() => {
let data = “用户数据”
it.next(data);
}, 1000)
}
function getOrders() {
setTimeout(() => {
let data = “订单数据”
it.next(data);
}, 1000)
}
function getGoods() {
setTimeout(() => {
let data = “商品数据”
it.next(data);
}, 1000)
}
function* gens() {
let users = yield getUsers();
console.log(users)
let orders = yield getOrders();
console.log(orders)
let goods = yield getGoods();
console.log(goods)
}
//调用生成器函数
let it = gens();
it.next();
## 13、promise
### 13.1promise介绍与基本使用
Promise是es6引入的异步编程的新解决方案(解决异步编程的回调地狱问题)。语法上Promise是一个构造函数,用来封装异步操作并可以取得其成功和失败的结果