一、ES6介绍
ECMAScript 6.0 (以下简称ES6) 是JavaScript语言的下一代标准.使得JavaScript语言可以用来编写复杂
- ES5语言的先天性不足。比如变量提升、内置对象的方法 不灵活、模块化实现不完善等等
- 为了后面vue、尤其是react框架做好了准备
二、let和const命令
1.let 声明变量, 没有变量提升
代码如下:
console.log(a); // 报错
let a =10;
2.是个块作用
代码如下:
if(1===1){
let b = 10;
}
console.log(b);
3. 不能重复声明
let a =2;
let a =4;
console.log(a);
4. const 声明常量 一旦被声明 无法修改
console.log(max);
if(1==1){
const max = 40;
}
const max = 30;
const max = 40;
console.log(max);
const person = {
name:"三和"
}
person.name = "sanhe" // √
person = { // X
age:20
}
console.log(person); // {name: 'sanhe'}
4. 作用: 1 for循环是个经典例子
var arr =[]; // 10
const arr =[]; // 4
for(let i=0;i<10;i++){
arr[i] = function(){
return i;
}
}
console.log(arr[4]());
5. 作用: 2 不会污染全局变量
let RegExp = 10;
console.log(RegExp); // 10
console.log( window.RegExp); // ƒ RegExp() { [native code] }
// 建议: 在默认情况下使用const, 而只有在你知道变量值需要被修改的情况下使用let
三、模板字符串
模板字符串: 使用tab键上面的反引号`` ,插入变量时使用${变量名}
const oBox = document.querySelector(".box")
let id = 1;
let name = "sanhe";
let htmlStr = ` <ul>
<li>
<p class="${id}">${name}</p>
</li>
</ul>`;
oBox.innerHTML = htmlStr;
// oBox.innerHTML = "<ul><li><p id=" + 1 + ">" + name + "</p></li></ul>"
四、函数之默认值、剩余参数
1.带参数默认值的函数
function add(a,b=20){
return a+b;
}
console.log(add(30));
2. 默认的表达式也可以是一个函数
function add(a,b = getVal(5)){
return a+b;
}
function getVal(val){
return val+5;
}
console.log(add(30));
3.剩余参数: 由三个... 和一个紧跟着的具名参数指定 ...keys
function pick(obj, ...keys) {
// ...keys 解决了arguments 的问题
// console.log(keys);
let result = Object.create(null);
for(let i=0;i<keys.length;i++){
result[keys[i]] = obj[keys[i]]
}
return result;
}
let book = {
title: "es6教程",
author: "啦啦啦",
year: "2022",
}
let bookData = pick(book, "title", "author", "year");
console.log(bookData);
五、扩展的对象的功能
//es6直接写变量和函数,作为对象的属性方法
const name = "sanhe",
age = 20;
const person = {
name, // 等价于name:name,
age,
sayName() {
console.log(this.name);
}
}
person.sayName();
// 用法
let cart = {
wheel: 4,
set(newVal) {
if (newVal < this.wheel) {
throw new Error('轮子数太少了')
}
this.wheel = newVal;
},
get() {
return this.wheel;
}
}
// console.log(cart.get()); // 4
cart.set(6)
console.log(cart.get()); // 6
// 对象的方法
// is()===
// 比较两个值是否严格相等
console.log(NaN === NaN); // false
console.log(Object.is(NaN === NaN)); // false
// assign() 对象的合并
// Object.assign(target,obj1,obj2)
// 返回合并之后的新对象
let newObj = Object.assign({}, { a: 1 }, { b: 2 });
console.log(newObj); // {a: 1, b: 2}
六、Symbol类型
//原始数据类型Symbol, 它表示是独一无二的值
// 最大的用途: 用来定义对象的私有变量
const name = Symbol("name");
const name2 = Symbol("name");
console.log(name === name2); //false
let s1 = Symbol("s1");
console.log(s1); // Symbol(s1)
// let obj = {};
// obj[s1] = 'sanha';
// 上面等价于
let obj = {
[s1] : 'sanhe'
}
// 如果用Symbol定义的对象中的变量,取值时一定要用 [ 变量名 ]
console.log(obj[s1]); // sanhe
// 获取Symbol声明的属性名(作为对象的key)
let s = Object.getOwnPropertySymbols(obj)
console.log(s[0]); //Symbol(s1)
let m = Reflect.ownKeys(obj);
console.log(m); //[Symbol(s1)]
七、Set集合数据类型
// 集合: 表示无重复值的有序列表
let set = new Set();
console.log(set); //Set(0)
// 添加元素
set.add(2);
set.add([1,34,56]);
// 删除元素
set.delete(2);
// 校验某个值是否在set中
console.log(set.has('4'));// false true/false
console.log(set.size);
console.log(set);
// set.forEach((val,key) => {
// console.log(val); //[1, 34, 56]
// console.log(key); //[1, 34, 56]
// });
// 将set转化成数组
let set2 = new Set([1,2,3,4,5,5,5,6]);
console.log(set2); // Set(6) {1, 2, 3, 4, 5, …}
// 扩展运算符
let arr = [...set2]
console.log(arr); // (6) [1, 2, 3, 4, 5, 6]
// 1.set中对象的引用无法被释放
let set3 = new Set(),obj={};
set3.add(obj);
// 释放当前的资源
obj = null;
console.log(set3);
// WeakSet
// 1. 不能传入费=非对象类型的参数
// 2. 不可迭代
// 3. 没有forEach()
// 4. 没有size属性
let set4 = new WeakSet(),obj1={};
set4.add(obj1);
// 释放当前的资源
obj1 = null;
console.log(set4);
八、Map数据类型
// Map类型是键值对的有序列表, 键和值是任意类型
// set设置 get获取
let map = new Map();
map.set('name', "张三");
map.set('age', 20);
console.log(map.get('name')); // 张三
console.log(map); // Map(2) {'name' => '张三', 'age' => 20}
map.has('name') // true
map.delete(); // 清除
map.set(['a', [1, 2, 3]], 'hello') // Map(3) {'name' => '张三', 'age' => 20, Array(2) => 'hello'}
console.log(map);
let m = new Map([
['a', 1],
['b', 2]
])
console.log(m); //Map(2) {'a' => 1, 'b' => 2}
九、数组的扩展方法1
// 数组的方法 from() of()
// 1. from() 将伪数组转换成真正的数组
function add(){
console.log(arguments); // Arguments(3) [1, 2, 3, callee: ƒ, Symbol(Symbol.iterator): ƒ]
// es5 转换
let arr = [].slice.call(arguments);
console.log(arr);//(3) [1, 2, 3]
// es6 写法
let arr1 = Array.from(arguments);
console.log(arr1); //(3) [1, 2, 3]
}
add(1,2,3)
let lis = document.querySelectorAll('li');
console.log(Array.from(lis)); // (4) [li, li, li, li]
// 扩展运算符 将伪数组转换成真正的数组
console.log([...lis]);
// from() 还可以接受第二个参数, 用来对每个元素进行处理
let licontent = Array.from(lis,ele=>ele.textContent);
console.log(licontent); //(4) ['1', '2', '3', '4']
// 2. of() 将任意的数据类型,转换成数组
console.log(Array.of(3,4,43,[34,5,"67"],{id:"1"})); //(5) [3, 4, 43, Array(3), {…}]
// 3. copywithin(下标0开始,下标结束但不包括) 复制
// 比如下面的 (0,5)从下标0开始 一直到下标4(不包括5) 只剩9替换1所以为[ 9, 2, 3, 7, 8, 9]
console.log([1,2,3,7,8,9].copyWithin(0,5)); // [ 9, 2, 3, 7, 8, 9]
// 4. find() findIndex()
// find() 找出第一个符合条件的数组成员
console.log( [1,2,-10,-20,3].find(n => n<0)); // -10
// findIndex() 找出第一个符合条件的数组成员的索引
console.log( [1,2,-10,-20,3].findIndex(n => n<0));//2
十、数组的扩展方法2
// entries() keys() values() 返回一个遍历器 可以使用for..of循环进行遍历
// keys() 对键名遍历
// values() 对值遍历
// entries() 对键值对遍历
console.log(["a","b"].keys()); //Array Iterator {}
for(let index of ["a","b"].keys()){
console.log(index); // 0 1
}
for(let index of ["a","b"].values()){
console.log(index); // a b
}
for(let index of ["a","b"].entries()){
console.log(index); // [0, 'a'] [1, 'b']
}
// includes() 返回一个布尔值, 表示某个数组是否包含给定的值
console.log([1,2,3].includes(2)); // true
console.log([1,2,3].includes("4")); //false
console.log([1,2,3].indexOf("4")); //-1
十一、迭代器iterator的用法
// Interator
// 是一种新的遍历机制
// 1. 迭代器是一个接口,能快捷的访问数据, 通过Symbol.iterator来创建迭代器 通过迭代器的next()获取迭代之后的结果
// 2. 迭代器是用于遍历数据结构的指针(数据库的游标)
// 使用迭代
const items = ['one', 'two', 'three'];
// 1. 创建新的迭代器
const ite = items[Symbol.iterator]();
console.log(ite.next()); //{value: 'one', done: false} done 如果为false,表示遍历继续 如果为true,表示遍历完成
console.log(ite.next()); //{value: 'two', done: false}
console.log(ite.next());//{value: 'two', done: false}
console.log(ite.next());//{value: 'two', done: true}
十二、生成器Generator的用法
// generator函数 可以通过yield关键字,将函数挂起, 为了改变执行流提供了可能,同时为了异步编程提供了方案
// 它普通函数的区别
// 1. function后面 函数名之前有个*
// 2. 只能在函数内部使用yield表达式, 让函数挂起
function* func(){
return 2;
}
// 返回一个遍历器对象 可以调用next()
// console.log(func().next());
// 总结: generator函数是分段执行的,yield语句是暂停执行 而next()是恢复
function* add(){
console.log('start'); // start
// x 不是yield '2' 的返回值,他是next()调用, 恢复当前yield() 执行传入的实参
let x = yield '2'; // {value: '2', done: false}
console.log('one:'+x); // one:10
let y = yield '3'; // {value: '3', done: false}
console.log('two:'+y); // two:20
return x+y; // {value: 30, done: true}
}
let fn = add();
console.log(fn.next());
console.log(fn.next(10));
console.log(fn.next(20));
// 使用场景: 为具备interator接口的对象提供了遍历操作
function* objectEntries(obj){
const propKeys = Object.keys(obj);
for(const propkey of propKeys){
yield [propkey,obj[propkey]]
}
}
const obj = {
name:"es6",
age:20
}
obj[Symbol.iterator] = objectEntries;
console.log(obj);
for(let [key,value] of objectEntries(obj)){
console.log(`${key}:${value}`);
}
十三、Generator的应用
// Generator 部署ajax操作,让异步代码同步化
// 加载loading...页面
// 数据加载完成... (异步操作)
// loading关闭掉
function* load() {
loadui();
yield loadData();
loadend();
}
let cc = load();
cc.next();
function loadui() {
console.log('loading显示');
}
function loadData() {
setTimeout(() => {
console.log('内容加载完成');
cc.next();
},1000)
}
function loadend() {
console.log('loading隐藏');
}
十四、Promise的基本使用
Promise 承诺
相当于一个容器,保存着未来才会结束的事件(异步操作)的一个结果
各种异步操作都可以用同样的方法进行处理 axios
特点:
1. 对象的状态不受外界影响,处理异步操作 三个状态 pending(进行) Resolved(成功) Rejected(失败)
2. 一旦状态改变,就不会再变, 任何时候都可以得到这个结果
// 第一种
let pro = new Promise((resolved,rejected)=>{
let res = {
code:201,
data:{
name:"张三"
},
error:'失败'
}
setTimeout(()=>{
if(res.code === 200){
resolved(res.data);
}else{
rejected(res.error)
}
},1000)
})
// console.log(pro);
pro.then((val)=>{
console.log(val);
},(err)=>{
console.log(err);
})
// 第二种
function timeOut(ms){
return new Promise((resolved,rejected)=>{
setTimeout(()=>{
resolved('成功')
},ms)
})
}
timeOut(2000).then((val)=>{
console.log(val);
})
十五、使用Promise封装ajax
// then() 方法
// then() 第一个参数是relove回调函数, 第二个参数是可选的,是reject状态回调的函数
// then() 返回一个闲的Promise实例, 可以采用链式编程
getJSON('url')
.then(data=>{
console.log(data);
}).catch(err=>{
console.log(err);
})
十六、Promise对象的其他方法
// resolve() reject() all() race() done() finally()
// resolve() 能将现有的任何对象转换成promise对象
// let p = Promise.resolve('foo'); 等价于下面的
let p = new Promise(resolve=>resolve('foo'));
console.log(p);
p.then(data=>{
console.log(data);
})
// all() 应用: 一些游戏类的素材比较多, 等待图片、flash、静态资源文件 都加载完成, 才进行页面的初始化
let promise1 = new Promise((resolve,reject)=>{});
let promise2 = new Promise((resolve,reject)=>{});
let promise3 = new Promise((resolve,reject)=>{});
let p4 = Promise.all([promise1,promise2,promise3]);
p4.then(()=>{
// 三个都成功 才成功执行then里面的代码
}).catch(()=>{
// 如果有一个失败,则失败
})
// race() 某个异步请求设置超时时间, 并且在超时后执行相应的操作
// 1. 请求图片资源
function requestImg(imgSrc){
return new Promise((resolve,reject)=>{
const img = new Image();
img.onload = function(){
resolve(img)
}
img.src = imgSrc;
})
}
function timeout(){
return new Promise((resolve,reject)=>{
setTimeout(()=>{
reject(new Error('图片请求超时'))
},3000)
})
}
Promise.race([requestImg('https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.jj20.com%2Fup%2Fallimg%2F1115%2F0ZR1095111%2F210ZP95111-7-1200.jpg&refer=http%3A%2F%2Fimg.jj20.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1660806408&t=79a35f949ff42aafecb6d8aa56bd01ca'),timeout()])
.then((data)=>{
console.log(data);
document.body.appendChild(data);
}).catch((err)=>{
console.log(err);
})
十七、async的用法
// Genarator Promise async 1.解决回调地域 2.使得异步操作更加方便
// 作用: 使得异步操作更加方便
// 基本操作: async 它会返回一个Promise对象 then catch
// async是Generator的一个语法糖
// 注意点: 用await命令一定在async函数中,不能单独使用
async function f(){
// return await 'hello async';
let s = await 'hello,word';
let t = await s.split('');
return t
}
// 如果asynv函数中有多个await 那么then函数会等待所有的await指令 运行完的结果 才去执行
f().then(v=>{console.log(v)}).catch(e=>{console.log(e)})
async function f2(){
// throw new Error('出错了')
// await Promise.reject('错误');
try {
await Promise.reject('错误');
} catch (error) {
}
return await Promise.resolve('成功');
}
f2().then(v=>{console.log(v)}).catch(e=>{console.log(e)})
18、class类的用法
// es5 造类
// function Person1(name,age){
// this.name = name;
// this.age = age;
// }
// Person1.prototype.sayName1 = function(){
// return this.name;
// }
// let p1 = new Person1('es6',30)
// console.log(p1); // Person {name: 'es6', age: 30}
class Person{
// 实例化的时候会立即被调用
constructor(name,age){
this.name = name;
this.age = age;
}
// sayName(){
// return this.name;
// }
// sayAge(){
// return this.age;
// }
}
// 通过Object.assgin()方法一次性向类中添加多个方法
Object.assign(Person.prototype,{
sayName(){
return this.name;
},
sayAge(){
return this.age;
}
})
let p1 = new Person('es6',21);
console.log(p1);
19、类的继承
// 使用关键字 extends
class Anmal{
constructor(name,age){
this.name = name;
this.age = age;
}
sayName(){
return this.name;
}
sayAge(){
return this.age;
}
}
class Dog extends Anmal{
constructor(name,age,color){
super(name,age);
// Anmal.call(this,name,age);
this.color = color;
}
// 子类自己的方法
sayColor(){
return this.color;
}
// 重写父类的方法
sayName(){
return this.name + super.sayAge() + this.color;
}
}
let d1 = new Dog("大黄",4,'red');
// console.log(d1);
console.log(d1.sayName());
20、ES6的模块化实现
html:
// CommonJs 和 AMD
// import {name} from './modules/index.js';
import Person,{name,age,sayName} from './modules/index.js';
// console.log(name);
// import * as f from './modules/index.js';
// console.log(f);
// console.log(f.default);
console.log(Person);
let p = new Person();
p.sayAge();
index.js:
// es6模块功能主要有两个命令构成: export 和 import
// exxport 用于规定模块的对外接口 import用于输入其他模块提供的功能
// 一个模块就是独立的文件
// default 只能在一个js文件中使用一次
export const name = "张三";
export const age = 18;
export function sayName(){
return 'my name is es6'
}
const obj = {
foo:"foo"
}
// export default obj;
class Person{
constructor(){
}
sayAge(){
console.log(15);
}
}
export default Person;