1 ES6
1 ES6介绍
为什么要学习ES6?
ES5语言的先天性不足。比如变量提升、内置对象的方法不灵活、模块化实
现不完善等等- 为了后面
vue、尤其是react框架做好了准备 - 目前大部分公司的项目都在使用
es6
ES6简介:
ECMAScript 6.0 (以下简称ES6)是JavaScript语言的下一代标准,已经在
2015年6月正式发布了。它的目标,是使得JavaScript语言可以用来编写复杂的大型应用程序,成为企业级开发语言
ES6既是一个历史名词,也是一个泛指,含义是5.1版以后的JavaScript的下一
代标准,涵盖了ES2015、ES2016、ES2017 等等,而ES2015则是正式名称,特
指该年发布的正式版本的语言标准
ES6新特性:
- let和
const命令 es6的模板字符串- 增强的函数
- 扩展的字符串、对象、数组功能
- 解构赋值
- Symbol
- Map和Set
- 迭代器和生成器
- Promise对象
- Proxy对象
async的用法- 类class
- 模块化实现
浏览器的支持:
各大浏览器的最新版本,对ES6的支持可以查看kangax.github.io/compat-table/es6/ 随着时间的推移,支持度已经越来越高了,超过90%的ES6语法特性都实现了。
前端工具:强大的babel
- 被称为下一代的JavaScript编译器。可以将
es6的代码转换成es5的代码,从而让浏览器获得支持 - 这个课程我们只需要知道前端工具babel这个工具的作用,在这里不做过多的赘述
参考文献:
ES6阮-峰教程: http://es6.ruanyifeng.com
MDN教程: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript
2 let和const
let声明的变量特性:
-
声明变量,没有变量提升
console.log(a); let a = 10; # 报错 -
是一个局部作用域
if(1===1){ let b = 10; } console.log(b) # 报错 -
不能重复声明,也就是不能覆盖
let a = 1; let a = 2; console.log(a); # 报错
const声明的变量:
-
const声明的是常量,一旦声明 不可修改const max = 30; max = 40; console.log(max) # 报错 -
const声明的常量属于局部作用域,也不能覆盖console.log(max) if(1===1){ const max = 30; } # 报错 -
可以修改对象
可修改对象的常量中的属性,但不能修改常量
const person = { name:'小马哥' } person.name = "alex"; console.log(person)
简单的应用:
-
使用var声明的变量,会有覆盖现象:
const arr = []; for (let i = 0; i<10; i++){ arr[i] = function(){ return i; } } console.log(arr[5]()); # 10 -
使用let和
const声明的变量,不会有覆盖现象:const arr = []; for (let i = 0; i<10; i++){ arr[i] = function(){ return i; } } console.log(arr[5]()); # 5 -
使用let和
const声明的变量,不会污染全局变量:let RegExp = 10; console.log(RegExp); console.log(window.RegExp);
建议:在默认情况下用
const,而只有在你知道变量值需要被修改的情况使用let
3 模板字符串
模板字符串的好处:
tab键上面的反引号
如果说你要拼接一串字符串,那么不需要咱们直接的+去拼接,使用反引号来拼接,拼接的变量使用${变量名}
函数的书写
<div class="box"></div>
<script>
const oBox = document.querySelector('.box');
let id = '1p', name = '刘大帅'
oBox.innerHTML = `
<ul>
<li>
<p id="${id}">${name}</p>
</li>
</ul>
`
</script>
4 函数
4-1 箭头函数
es6箭头函数的使用:
function(){} ==== ()=>{}
箭头函数的使用带来的问题:
1.使用箭头函数 this的指向发生了改变
2.使用箭头函数 arguments不能使用
-
es5函数let add = function(a,b){ return a+b; } -
es6函数es6的箭头函数
使用=> 来定义 function(){}等于与()=>{}
// 两个参数
let add = (a,b)=>{
return a+b;
}
console.log(add(10,20))
// 一个参数
let add = val =>{
return val + 5;
}
// 简易写法
let add = val => (val+5);
console.log(add(10))
let add = val => val;
console.log(add())
let add = (val1,val2) => val1+val2;
console.log(add(10,20))
let fn = ()=> "hello world"+"lxx";
console.log(fu());
let getObj = id => {
return {
id: id,
name: "刘大帅",
}
}
let obj = getObj(1);
console.log(obj);
// 简易写法
let getObj = id => ({id: id,name: "刘大帅"})
let obj = getObj(1);
console.log(obj);
let fn = (function(){
return function(){
console.log('hello es6');
}
})();
fn();
// 简易写法
let fn = (()=>{
return ()=>{
console.log('hello es6');
}
})();
fn();
4-2 带参数默认值的函数
<script>
// 1.带参数默认值的函数
// es5的写法
function add(a,b) {
a = a || 10;
b = b || 20;
return a + b
};
console.log(add());
// es6的写法
function add(a=10,b=20){
return a+b
};
console.log(add())
</script>
默认的表达式也可以是一个函数
function add(a,b=getVal(5)){
return a+b
};
function getVal(val){
return val+5
};
console.log(add(10));
4-3 剩余运算符
<script>
function pick(obj) {
let result = Object.create(null);
for (let i = 0; i < arguments.length; i++) {
result[arguments[i]] = obj[arguments[i]]
}
return result
}
let book = {
title: 'es6的教程',
author: '小马哥',
year: 2019,
}
let bookData = pick(book, 'title', 'year');
console.log(bookData);
</script>
// es6写法
function pick(obj,...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:2019,
}
let bookData = pick(book, 'title', 'year');
console.log(bookData);
简易写法:
function checkArgs(...args){
console.log(args);
console.log(arguments);
}
checkArgs('a', 'b', 'c')
4-4 扩展运算符
将一个数组分割,并将各个项作为分离的参数传给函数
//es5
const arr = [10,20,40,30,90,100];
console.log(Math.max.apply(null,arr));
// es6 扩展运算法更方便
console.log(Math.max(...arr))
4-5 this指向
// es5中的this指向:取决于调用该函数的上下文对象
let PageHandle = {
id: 123,
init: function(){
document.addEventListener('click', function(event){
this.doSomeThings(event.type);
}.bind(this), false)
},
doSomeThings: function(type){
console.log(`事件类型:${type},当前id:${this.id}`);
}
}
PageHandle.init();
// es6中的this没有this绑定
let PageHandle = {
id: 123,
init: function(){
// 箭头函数没有this指向,箭头 函数内部this值只能通过查找作用域链来确定,一旦使用箭头函数,当前就不存在作用域链
document.addEventListener('click', (event)=>{
this.doSomeThings(event.type);
},false)
},
doSomeThings: function(type){
console.log(`事件类型:${type},当前id:${this.id}`);
}
}
PageHandle.init();
4-6 箭头函数的注意事项
-
使用箭头函数后,内部就不会在有arguments
let getVal = (a,b) =>{ console.log(arguments); return a+b; } console.log(getVal(1,3)); // 报错 -
使用箭头函数后,this指向的是父级
-
箭头函数不能使用new关键字来实例化对象
let Person = () =>{}; //function函数也是一个对象,但是箭头函数不是个对象,它其实就是一个函数的语法糖 let p = new Person();
5 解构赋值
- 解构赋值是对赋值运算符的一种扩展
- 它针对数组和对象来进行操作
- 优点:代码书写上简洁易读
let node = {
type: 'iden',
name: 'foo'
}
// let type = node.type;
// let name = node.name;
let {type, name} = node;
console.log(type, name);
// iden foo
let obj = {
a: {name: '张三'},
b: [],
c: 'hello world'
}
let {a} = obj;
console.log(a)
// {name: '张三'}
// 剩余运算符
let {a,...res} = obj
console.log(a)
console.log(res)
默认值:
let {a, b=30} = {a:20}
console.log(a,b)
对数组解构:
let arr = [1,2,3];
let [a,b] = arr;
console.log(a,b);
// 1 2
可嵌套:
let [a,[b],c] = [1,[2],3];
console.log(a,b,c)
6 对象扩展功能
-
es6直接写入变量和函数,作为对象的属性和方法const name = '小马哥', age=20; const person = { name, // 等价于name:name(注:属性值和属性名要相同) age, sayName(){ console.log(this.name); } // 方法的简写 } person.sayName();function fn(x, y) { return {x, y}; } console.log(fn(10, 20));const obj = {}; obj.isShow = true; const name = 'a'; obj[name+'bc'] = 123; console.log(obj); ----------------------------------- // 方法的表达式: const name = 'a'; const obj = { isShow: true, [name+'bc']: 123, ['f'+name](){console.log(this);} } console.log(obj); -
对象的方法
// is() === // 比较两个值是否严格相等 console.log(NaN === NaN); // false console.log(Object.is(NaN,NaN)); // true // assign() // 对象的属性合并 // Object.assign(target, obj1, obj2, ...) // 返回合并之后的新对象 let newObj = Object.assign({},{a:1},{b:2}) console.log(newObj)
7 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 = {[s1]: '大帅比'};
console.log(obj);
// 获取值:如果用Symbol定义的对象中的变量,取值时定要用[变量名]
console.log(obj[s1]);
// console.log(obj.s1); undefined
// 私有属性,循环没有值
for (let key in obj){
console.log(key);
} // 空
// 私有属性,对象取值为空数组
console.log(Object.keys(obj));
// 获取Symbol声明的属性名(作为对象的key)
// 方法1:
let s = Object.getOwnPropertySymbols(obj);
console.log(s[0]);
// 方法2:反射
let m = Reflect.ownKeys(obj);
console.log(m[0]);
8 Set数据类型
集合:表示无重复值的有序列表
let set = new Set();
console.log(set);
// 添加元素
set.add(2);
set.add('4');
set.add(['hello',1,2,3]);
console.log(set);
// 删除元素
set.delete(2);
console.log(set);
// 校验某个值是否在set中
console.log(set.has('4')); // 有true,无false
// 查看集合的长度
console.log(set.size);
// 遍历(只针对set中的数组)
set.forEach((val,key)=>{
console.log(val);
console.log(key);
})
// 将set转换成数组
let set2 = new Set([1,2,3,3,3,4]);
// 扩展运算符
let arr = [...set2]
console.log(arr);
WeakSet:
// 问:set中对象的引用无法被释放,使用WeakSet
let set3 = new WeakSet(),obj = {};
set3.add(obj);
// 释放当前资源
obj = null;
console.log(set3);
// WeakSet
// 1.不能传入非对象类型的参数
// 2.不可迭代
// 3.没有forEach()方法
// 4.没有size属性
9 Map数据类型
// Map类型是健值对的有序列表,键和值是任意类型
let map = new Map();
// 添加值
map.set('name', '张三');
map.set('age', 20);
console.log(map);
// 获取值
console.log(map.get('name'));
// 查询某个值是否存在
console.log(map.has('name')); // true,false
// 删除名
map.delete('name');
console.log(map);
// 清空值
map.clear();
console.log(map);
// 创建map方式2:
let m = new Map([['a',1],['c',2]]);
console.log(m);
// 同样map也有WeakMap,这就不在赘述
10 数组类型
-
方法1:
from()from()将伪数组转换成真正的数组function add() { // console.log(arguments); // es5转换 // let arr = [].slice.call(arguments); // console.log(arr); // es6写法 let arr = Array.from(arguments); console.log(arr); } add(1, 2, 3);应用:
<ul> <li>1</li> <li>2</li> <li>3</li> </ul>// 应用: let lis = document.querySelectorAll('li'); // from转换 console.log(Array.from(lis)); // [li, li, li] // 扩展运算符转换 console.log([...lis]); // [li, li, li] // from() 还可以有第二个参数,用来对每个元素进行处理 let liContents = Array.from(lis, ele => ele.textContent); console.log(liContents); // ['1', '2', '3'] -
方法2:
of()将任意的数据类型,转换成数组
console.log(Array.of(3, 11, 20, '30')); -
方法3:
copyWithin()数组内部将指定位置的元素复制到其它的位置,返回当前数组
// 从3位置往后的所有数值,替换从0位置往后的三个数值 console.log([1,2,3,8,9,10].copyWithin(0,3)); -
方法4:
find()和findIndex()find()找出第一个符合条件的数组成员let num = [1,2,-10,-20,9,2].find(n => n<0); console.log(num);findIndex()找出第一个符合条件的数组成员的索引let numIndex = [1,2,-10,-20,9,2].findIndex(n => n<0); console.log(numIndex); -
方法5:
entries() keys() values()返回一个遍历器,可以使用数组的for...of循环进行遍历
for (let index of ['a','b'].keys()){ // 对key的遍历 console.log(index); // 0 1 } for (let ele of ['a','b'].values()){ // 对value的遍历 console.log(ele); // a b } for (let [index,ele] of ['a','b'].entries()){ // 对键值对的遍历 console.log(index,ele); // 0 'a' // 1 'b' } let letter = ['a','b','c']; let it = letter.entries(); console.log(it.next().value); // 迭代取值 console.log(it.next().value); console.log(it.next().value); -
方法6:
includes()返回一个
bool值,表示数组是否包含给定的值console.log([1,2,3].includes(2)); // true console.log([1,2,3].includes('4')); // false
11 迭代器
Iterator 是一种新的遍历机制
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: 'three', done: false}
console.log(ite.next()); // 返回一个对象
// {value: undefined, done: true}
12 生成器
generator函数。可以通过yield关键字,将函数挂起,为了改变执行流提供了可能,同时为了做异步编程提供了方案
它普通函数的区别:
1.function后面,函数名之前有个*
2.只能在函数内部使用yield表达式,让函数挂起
function* func() {
yield 2;
yield 3;
}
// 返回一个遍历器对象,可以调用next()
let fn = func(); // 此时不执行函数。
console.log(fn.next());
// {value: 2, done: false}
console.log(fn.next());
// {value: 3, done: false}
console.log(fn.next());
// {value: undefined, done: true}
总结:
generator函数是分段执行的。yield语句是暂停执行,而next()是恢复执行。
function* add() {
console.log('start');
// x不是yield '2'的返回值,它是next()调用恢复当前yield()执行传入的实参
let x = yield '2';
console.log('one:'+x);
let y = yield '3';
console.log('two:'+y);
return x+y;
}
const fnn = add();
console.log(fnn.next());
// start
// {value: '2', done: false}
console.log(fnn.next(20));
// one:20
// {value: '3', done: false}
console.log(fnn.next(30));
// two:30
// {value: 50, done: true}
-
使用场景1(生成器主要用于异步)
function* objectEntries(obj) { // 获取对象的所有的key保存到数字中[name,age] const propKeys = Object.keys[obj]; for (const propkey of propKeys){ yield [propkey,obj[propkey]] } } const obj = { name: '刘大帅', age: 18 } obj[Symbol.iterator] = objectEntries; console.log(obj); for (let [key,value] of objectEntries(obj)){ console.log(`${key}:${value}`); } -
使用场景2
function* main() { let res = yield request("https://...com"); console.log(res); // 执行后面的操作 console.log('数据请求完成。继续操作。。') } const ite = main(); ite.next(); function request(url) { $.ajax({ url, method: 'get', success(res){ ite.next(res); } }) }Generator 部署ajax操作,让异步代码同步化
-
使用场景3
function* load() { loadUI(); yield showData(); hideUI(); } let itLoad = load(); itLoad.next(); function loadUI() { console.log('加载loading...页面'); } function showData() { // 模拟一步操作 setTimeout(() =>{ console.log('数据加载完成...'); itLoad.next(); }, 1000); } function hideUI() { console.log('隐藏loading...页面'); }
13 Promise对象
Promise是一个异步编程的解决方案。相当与一个容器,它保存着未来才会结束的事件(异步的操作)的一个结果,各种异步操作都可以用同样的方法进行处理
特点:
1.对象的状态不受外接影响,处理异步操作三个状态 pending(进行中)Resolved(成功)Rejected(失败)
2.一旦状态改变,就不会再变,任何时候都可以得到这个结果
用法:
let pro = new Promise(function (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('hello promise success!')
}, ms)
})
}
timeOut(2000).then((val)=>{
console.log(val);
});
13-1 then方法介绍
// then() 方法:
// then() 第一个参数是relove回调函数,第二个参数是可选的,是reject状态回调的函数
// then() 返回一个新的promise实例,可以采用链式编程
// 比如说:
getJSON('http://...com').then((data)=>{
console.log(data); // 成功后返回
}).catch(err=>{
console.log(err); // 失败后返回
})
/*
catch(err=>{}) 等价于 then(null,err=>{})
*/
自己封装的方法:
const getJSON = function(url){
return new Promise((resolve,reject)=>{
const xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.onreadystatechange = handler;
xhr.responseType = 'json';
xhr.setRequestHeader('Accept', 'application/json');
// 发送
xhr.send();
function handler() {
console.log(this);
if (this.readyState === 4){
if (this.status === 200){
resolve(this.response);
}else {
reject(new Error(this.statusText))
}
}
}
})
}
getJSON('https://...com').then((data)=>{
console.log(data);
},(error)=>{
console.log(error);
})
13-2 resolve方法
作用:能将现有的任何对象转换成promise对象
该方法跟reject方法几乎一样
// let p = Promise.resolve("foo"); 等同于以下
let p = new Promise(resolve => resolve('foo'));
console.log(p);
p.then((data)=>{
console.log(data);
})
13-3 all方法
all方法:异步并行操作,一起做事
let n1 = new Promise((resolve,reject)=>{});
let n2 = new Promise((resolve,reject)=>{});
let n3 = new Promise((resolve,reject)=>{});
// 怎么调用呢:
let n4 = Promise.all([n1,n2,n3]);
n4.then(()=>{
// 三个都成功,才成功返回
}).catch(err=>{
// 如果有一个失败,则失败
})
应用:一些游戏类的素材比较多,等待图片、flash、静态资源文件。都加载文成,才进行页面的初始化。
13-4 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://..'),timeout()]).then(res=>{
console.log(res);
document.body.appendChild(res);
}).catch(err=>{
console.log(err);
})
13-5 done和finally方法
不管Promise方法是否成功,都会执行。
列:
Promise.race([requestImg('https://'),timeout()]).then(res=>{
console.log(res);
document.body.appendChild(res);
}).catch(err=>{
console.log(err);
}).done()
14 async用法
async异步操作:它使我们的异步操作更加方便
基本操作:async它会返回一个Promise对象
async是Generator的一个语法糖
async function fn() {
// await命令必须在async中
let s = await 'hello async';
let data = await s.split('');
return data;
}
// 如果async函数中有多个await,那么then函数会等待所有的await指令,运行完的结果采取执行。
fn().then(value => {console.log(value);}).catch(err=>{
console.log(err)})
// ['h', 'e', 'l', 'l', 'o', ' ', 'a', 's', 'y', 'n', 'c']
15 class类
// es5 造类
// 定义属性
function Person(name,age) {
this.name = name;
this.age = age;
}
// 定义方法
Person.prototype.sayName = function () {
return this.name;
}
// 实例化
let p1 = new Person('刘大帅', 18)
console.log(p1);
// class
class Person2{
// 实例化时,会立即调用。
constructor(name,age) {
this.name = name;
this.age = age;
}
sayName(){
return this.name;
}
sayAge(){
return this.age;
}
}
// 实例化
let p2 = new Person2('大帅逼',22);
console.log(p2);
// 调用属性:
console.log(p2.name)
// 调用方法:
console.log(p2.sayAge())
// 通过Object.assign方法,一次性添加多个方法
Object.assign(Person2.prototype,{
sayNameAge(){
return (`${this.name}+${this.age}`);
},
sayAgeName(){
return (`${this.age}+${this.name}`);
}
})
console.log(p2);
15-1 class类的继承
// 使用关键字 extends
class Animal{
constructor(name,age) {
this.name = name;
this.age = age;
}
sayName(){
return this.name;
}
sayAge(){
return this.age;
}
}
class Dog extends Animal{
constructor(name,age,color) {
super(name,age); // 继承父类
this.color = color;
}
sayColor(){
return `${this.name}是${this.age}岁了,他的颜色是${this.color}`;
}
// 重写父类的方法
sayName() {
return this.name + super.sayAge() + this.color;
}
}
let d1 = new Dog('小黄', 9, 'red');
console.log(d1);
console.log(d1.sayColor());
console.log(d1.sayName());
16 模块化实现
es6 模块功能主要有两个命令构成:export和import
export用于规定模块的对外接口 import用于输入其他模块提供的功能
一个模块就是独立的文件
-
导入方式1:
js文件:
// 方式一:(推荐使用) export const name = '张三'; export const age = 18; export function sayName() { return 'my name is lxx'; }html文件:
// 方式1: import {name,age,sayName} from './modules/index' console.log(name,age,sayName()); -
导入方式2:
js文件:
// 方式二: const name = '张三'; const age = 18; function sayName() { return 'my name is lxx'; } export {name,age,sayName} const obj = {foo: 'foo'} // 对象 class Person{ constructor(name,age) { this.name = name; this.age = age; } } export default Person // 使用默认值导出html文件:
// 方式2: // import Person,{name,age,sayName} from './modules/index' import * as f from './modules/index'; console.log(f); // 取到当前对象 console.log(f.default);
17 axios库
axios就是基于Promise封装的方法:
中文网站:(http://www.axios-js.com/zh-cn/docs/)
2022-09-26 14:32:30 星期一

浙公网安备 33010602011771号