Symbol
ES6引入了一种新的原始数据类型symbol,表示独一无二的值,它是JS的第七种数据类型,是一种类似于字符串的数据类型。
symbol特点:
- symbol的值是唯一的,用来解决命名冲突的问题
- symbol值不能与其他数据进行运算
- symbol定义的对象属性不能使用for… in循环遍历,但是可以使用Reflect.ownKeys来获取对象的所有键名
七种数据类型
//USONB you are so niubility
//u undefined
//s String Symbol
//o object
//n null number
//b boolean
symbol对象的创建
//创建symbol 第一种
let s=Symbol();
console.log(s,typeof s);
let s2=Symbol('尚硅谷');
let s3=Symbol('尚硅谷');
console.log(s2==s3);
//Symbol.for创建 第二种
let s4=Symbol.for('尚硅谷')
let s5=Symbol.for('尚硅谷')
console.log(s4,typeof s4);
console.log(s4==s5);
//不能与其他数据类型进行运算
// let result =s+100
// let result =s>100;
// let result =s+"100"
//全都会报错
symbol创建对象属性
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
//向对象中添加方法 up down
let game={
}
//声明一个对象
let methods={
up:Symbol(),
down:Symbol()
};
game[methods.up]=function(){
console.log('我可以改变形状');
}
game[methods.down]=function(){
console.log('我可以快速下降');
}
console.log(game);
</script>
</body>
</html>
symbol的内置属性
除了定义自己使用的symbol值以外,ES6还提供了11个内置的symbol值,指向语言内部使用的方法。
(47条消息) es6 Symbol 的内置属性_ixygj197875的博客-CSDN博客
Symbol.hasInstance | 可以自己去控制类型检测(当其他对象使用instanceof 运算符,判断是否为该对象实例时,会调用该方法) |
---|---|
Symbol.isConcatSpreadable | concat是用来合并数组,Symbol.isConcatSpreadable是用来控制数组是否可以展开 |
Symbol.unscopables | 该对象指定了使用with关键字时,那些属性会被with环境排除 |
Symbol.match | 字符串方法,自动的,不需要手动执行 |
Symbol.replace | 字符串方法,自动的,不需要手动执行 |
Symbol.search | 字符串方法,自动的,不需要手动执行 |
Symbol.split | 字符串方法,自动的,不需要手动执行 |
Symbol.iterator | 对象进行for…of循环时,会调用Symbol.iterator方法,返回该对象对应的而原始数据类型 |
Symbol.toPrimitive | 该对象被转化为原始类型的值时,会调用这个方法,返回该对象对应的原始类型值 |
Symbol.toStringTag | 在该对象上面调用toString方法时,返回该方法的返回值 |
Symbol.species | 创建衍生对象时,会使用该属性 |
<script>
// class Person{
// static [Symbol.hasInstance](param){
// console.log(param);
// console.log("我被用来检测类型了");
// return true;//这里返回什么,最后就会显示什么
// }
// }
// let o={}
// console.log(o instanceof Person);
const arr=[1,2,3];
const arr2=[4,5,6];
arr2[Symbol.isConcatSpreadable]=true;//等于true,控制数组内的值可以展开
arr[Symbol.isConcatSpreadable]=false;//等于false,控制数组内的值不可以展开
console.log(arr.concat(arr2));//将数组进行合并
</script>
13-迭代器
迭代器(Iterator)是一种接口,为各种不同的数据结构提供统一的访问机制,任何数据结构只要部署Iterator接口,就可以完成遍历操作。
1.ES6创造了一种新的遍历命令for…of循环,Iterator接口主要提供for…of消费
2.原生具备Iterator接口的数据(可用于for of遍历)
- Array
- Arguments
- Set
- Map
- String
- TypedArray
- NodeList
3.工作原理
- 创建一个指针对象,指向当前数据结构的起始位置
- 第一次调用对象的next方法,指针自动指向数据结构的第一个成员
- 接下来不断调用next方法,指针一直往后移动,直到指向最后一个成员
- 每调用一次next方法返回一个包含value和done属性的对象
注:需要自定义遍历数据的时候,要想到迭代器
<script>
//声明一个数组
const xiyou =['唐僧','孙悟空','猪八戒','沙和尚']
// //使用for of遍历数组 遍历出来的是键值
// for(let v of xiyou){
// console.log(v);
// }
// //使用for in遍历数组 遍历出来的是键名
// for(let v in xiyou){
// console.log(v);
// }
// console.log(xiyou);
let iterator =i=xiyou[Symbol.iterator]();
//调用对象的next方法
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
</script>
自定义遍历数据实例
<script>
//声明一个对象
const banji = {
name: '终级一组',
stus: [
'小明',
'小红',
'小宁',
'小迪',
],
[Symbol.iterator](){
//索引变量
let index=0;
let _this=this;//让return里的this指向stus,也可以使用箭头函数实现
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);
} //返回错误banji is not iterable
// banji.stus.forEach(
// function (value, index, obj) {
// console.log("value = " + value);
// }
// )//可以遍历,但不符合面向对象的思想
</script>
生成器
生成器函数时ES6提供的一种异步编程解决方案,语法行为与传统函数完全不同
<script>
//生成器其实就是一个特殊的函数 异步编程的一种新的解决方案
//异步编程 之前用的是纯回调函数 node fs ajax mongodb(数据库)
//函数代码的分隔符
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());
//遍历
for(let v of gen()){
console.log(v);
}
</script>
生成器函数参数
<script>
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 iterator=gen('AAA');//整体传参
console.log(iterator.next());
//next 方法可以传入实参 返回的是上一个yield的返回值
console.log(iterator.next('BBB'));
console.log(iterator.next('CCC'));
console.log(iterator.next('DDD'));
</script>
生成器函数实例
实例1
<script>
//异步编程 文件操作 网络操作(ajax,request) 数据库操作
//1s 后控制台输出111 2s 后控制台输出222 3s 后控制台输出333
//回调地狱(之前的做法)
// setTimeout(() => {
// console.log(111);
// setTimeout(() => {
// console.log(222);
// setTimeout(() => {
// console.log(333);
// }, 3000)
// }, 2000)
// }, 1000)
//利用生成器函数
function one() {
setTimeout(() => {
console.log(111);
iterator.next();
}, 1000)
}
function two() {
setTimeout(() => {
console.log(222);
iterator.next();
}, 2000)
}
function three() {
setTimeout(() => {
console.log(333);
iterator.next();
}, 3000)
}
function* gen() {
yield one();
yield two();
yield three();
}
//调用生成器函数
let iterator = gen();
iterator.next();
</script>
实例2
<script>
//模拟获取 用户数据 订单数据 商品数据
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();
// //这样做不符合实际的场景 数据是关联的,有了用户,才会有订单,才会有商品
// getUsers();
// getOrders();
// getGoods();
</script>
promise
Promise 的含义
Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。
所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理。
Promise对象有以下两个特点。
**(1)对象的状态不受外界影响。**Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是Promise这个名字的由来,它的英语意思就是“承诺”,表示其他手段无法改变。
**(2)一旦状态改变,就不会再变,任何时候都可以得到这个结果。**Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为 resolved(已定型)。如果改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。
注意,为了行文方便,本章后面的resolved统一只指fulfilled状态,不包含rejected状态。
有了Promise对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。此外,Promise对象提供统一的接口,使得控制异步操作更加容易。
Promise也有一些缺点。
首先,无法取消Promise,一旦新建它就会立即执行,无法中途取消。
其次,如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。
第三,当处于pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。
如果某些事件不断地反复发生,一般来说,使用 Stream 模式是比部署Promise更好的选择。
基本用法
<script>
//实例化Promise对象
const p = new Promise(function (resolve, reject) {
setTimeout(function () {
let data = '数据库中的用户数据'
//resolve
// resolve(data);
let err = "数据请求失败"
reject(err);
}, 1000);
});
//调用Promise对象的then方法
p.then(function (value) {
console.log(value);
}, function (reason) {
console.error(reason);
})
</script>
promise读取文件
//1.引入fs模块
const fs =require('fs');
//2.调用方法,读取文件(原始方法)
fs.readFile('./promise读取文件/小记.md',(err,data)=>{
//如果失败,则抛出错误
if(err) throw err;
//如果没有出错,则输出内容
console.log(data.toString());
});
//使用promise封装
const p=new Promisse(function(resolve,reject){
fs.readFile("./promise读取文件/小记.md",(err,data)=>{
//判断如果失败
if(err) reject(err);
//如果成功
resolve(data);
});
});
p.then(function(value){
console.log(value);
},function(reason){
console.error(reason);
});
promise封装ajax
<script>
const p=new Promise((resolve,reject)=>{
//1.创建对象
const xhr = new XMLHttpRequest();
//2.初始化
xhr.open("GET", "https://api.apiopen.top/getJoke");
//3.发送
xhr.send();
//4.绑定事件,处理响应结果
xhr.onreadystatechange = function () {
//判断
if (xhr.readyState === 4) {
//判断响应状态码 200-299表示成功
if (xhr.status >= 200 && xhr.status < 300) {
//表示成功
resolve(xhr.response);
} else {
reject(xhr.status);
}
}
}
})
//指定回调
p.then(function(value){
console.log(value);
},function(reason){
console.error(reason);
})
</script>
promise-then方法
<script>
//创建promise对象
const p=new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve("用户数据");
// reject('出错啦');
},1000)
});
//调用then方法 then方法的返回结果是promise对象,对象状态由回调函数的执行结果决定
//1.如果回调函数中返回的结果是非promise类型的属性,状态为成功,返回值为对象的成功的值
// const result=p.then(value=>{
// console.log(value);
// //1.非promise类型的属性
// return 'iloveyou'; //函数中如果不写return默认返回值是undefined
// //2.是promise对象
// return new Promise((resolve,reject)=>{
// resolve('OK'); //这里成功就成功,这里失败就失败
// // reject('error');
// });
//3.抛出错误
// throw new Error('出错啦!');
// throw '出错啦';
// },reason=>{
// console.warn(reason);
// })
//then 可以链式调用,解决了回调地狱
p.then(value=>{
},reason=>{}).then(value=>{
})
// console.log(result);
</script>
promise-catch方法
<script>
const p=new Promise((resolve,reject)=>{
setTimeout(() => {
//设置p对象的状态为失败,并设置失败的值
reject("出错啦");
}, 1000);
});
// p.then(function(value){},function(reason){
// console.error(reason);
// });
//换成catch方法
p.catch(function(reason){
console.warn(reason);
})
</script>
Set
ES6 提供了新的数据结构 Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。
Set本身是一个构造函数,用来生成 Set 数据结构
声明一个set
<script>
//声明一个set
let s=new Set();
let s2=new Set(['大事儿','小事儿','好事儿','坏事儿','小事儿']);//会自动去重
console.log(s2);
//元素个数
console.log(s2.size);
//添加新的元素
s2.add('喜事儿')
//删除元素
s2.delete('坏事儿')
//检测是否含有某个元素
console.log(s2.has('好事儿'));
//清空
// s2.clear()
console.log(s2);
for(let v of s2){
console.log(v);
}
</script>
Map
类似于对象,也是键值对的集合。但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以做键。Map也实现了iterator接口,所以可以使用 扩展运算符 和**for…of…**进行遍历。
<script>
//声明Map
let m=new Map()
//添加元素
m.set('name','尚硅谷');
m.set('change',function(){
console.log('我们可以改变你!');
});
let key={
school:"河南科技学院"
};
m.set(key,['北京','上海','南阳'])
//第三种也可以写成这样
// m.set({
// school:"河南科技学院"
// },['北京','上海','南阳'])
//测量长度 size
console.log(m.size);
// 删除
m.delete('name');
//获取
console.log(m.get('change'));
console.log(m.get(key));
//清空
// m.clear()
// console.log(m);
//遍历
for(let v of m){
console.log(v);
}
</script>
模块化
模块化是指将一个大的程序文件,拆分成许多小的文件,然后将小的文件组合起来。
模块化的好处
- 防止命名冲突
- 代码复用
- 高维护性
模块化规范产品
ES6 之前的莫滑块规范有:
- CommonJS => NodeJS、Browserify
- AMD => requireJS
- CMD => seaJS
ES6模块化语法
模块功能主要由两个命令构成:export和import
- export命令用于规定模块的对外接口
- import命令用于输入其他模块提供的功能
分别暴露,统一暴露,默认暴露
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script type="module">
// //1.通用的导入方式
// //引入m1.js 模块内容
// import *as m1 from "./m1.js"
// console.log(m1);
// //引入m2.js 模块内容
// import *as m2 from "./m2.js"
// console.log(m2);
// //引入m3.js 模块内容
// import *as m3 from "./m3.js"
// console.log(m3);
// m3.default.change();
// //2.解构赋值的形式
// import{school,teach} from "./m1.js";
// import{school as guigu,findjob} from "./m2.js";//Uncaught SyntaxError: Identifier 'school' has already been declared
// //采用别名的形式
// import{default as m3} from "./m3.js";
// console.log(school);
// console.log(guigu);
// console.log(teach);
// console.log(m3);
//3.简便形式 针对默认暴露
import m3 from "./m3.js";
console.log(m3);
</script>
</body>
</html>
//m1.js
//分别暴露
export let school ='尚硅谷';
export function teach(){
console.log('我们可以教给你开发技能');
}
//m2.js
//统一暴露
let school="尚硅谷";
function findjob(){
console.log("我们可以帮助你找工作!!");
}
//
export{
school,findjob
}
//m3.js
//默认暴露
export default{
school:"ATGUIGU",
change: function(){
console.log("我们可以改变你!!");
}
}
ES新特性
ES7
<script>
//include
const mingzhu=['西游记','三国演义','红楼梦','水浒传'];
//判断
console.log(mingzhu.includes('西游记'));
console.log(mingzhu.includes('金瓶梅'));
//幂运算
console.log(2**10);
console.log(Math.pow(2,10));
</script>
ES8
async函数
- async函数的返回值是promise对象
- promise对象的结果由async函数执行的返回值决定
<script>
async function fn() {
//返回一个字符串
// return '尚硅谷';
//返回的结果不是一个promise类型的对象,返回的结果就是成功的promise
// return ;
//抛出错误,返回结果是一个失败的promise
// throw new Error('出错啦!')
//返回的结果是一个promise
return new Promise((resolve, reject) => {
// resolve('成功的数据');
reject('失败的错误');
});
}
const result = fn();
//调用then方法
result.then(value => {
console.log(value);
}, reason => {
console.warn(reason);
})
console.log(result);
</script>
await表达式
- await必须写在async函数中
- await右侧的表达式一般为promise对象
- await返回的是promise成功的值
- await的promise失败了,就会抛出异常,需要通过try…catch捕获处理
<script>
//创建一个promise对象
const p = new Promise((resolve, reject) => {
// resolve('用户数据');
reject('失败啦');
})
//await必须要放在async里面,但是async中可以没有await
async function main() {
try{
let result= await p;
console.log(result);
}catch(e){
console.log(e);
}
}
main();
</script>
对象方法扩展
<script>
//声明对象
const school ={
name:'尚硅谷',
cities:['北京','上海',"南阳"],
xueke:['前端','Java','大数据','运维']
};
// //获取对象所有的键
// console.log(Object.keys(school));
// //获取对象所有的值
// console.log(Object.values(school));
// //entries 获取的是一个数组,键和值
// console.log(Object.entries(school));
// //创建Map
// const m=new Map(Object.entries(school));
// console.log(m);
// console.log(m.get('cities'));
//返回对象属性的描述对象
// console.log(Object.getOwnPropertyDescriptors(school));
const obj=Object.create(null,{
name:{
//设置值
value:'尚硅谷',
//属性特性
writable:true,//是否可写
configurable:true,//是否可以删除
enumerable:true,//是否可以枚举
}
});//应用:获取完这个对象之后,进行深层次的克隆
</script>