课程链接
目录
- 相关介绍
- 什么是ECMA
- 什么是ECMAScript
- 为什么学习ES6
- let
- const
- 变量解构赋值
- 模板字符串
- 对象简化写法
- 箭头函数
- 函数参数的默认值
- rest参数
- 扩展运算符
- Symbol
- 迭代器
- 生成器函数与调用
- Promise
- 介绍与基本用法
- Promise封装读取文件
- Promise.prototype...then方法
- Promise.catch方法
- Set
- Map
- class类
- 介绍与初体验
- 静态成员
- 类的继承
- 重写
- get和set
- ES6的数值扩展
- 对象方法扩展
- 模块化
- 引入NPM包
相关介绍
什么是ECMA
中文名称是欧洲计算机制造商协会,这个组织的目标是评估、开发和认可电信和计算机标准。
什么是ECMAScript
是Ecma通过ECMA-262标准化的脚本程序设计语言
为什么学习ES6
- ES6的版本变动内容最多,具有里程碑意义
- ES6加入许多新的语法特性,变成实现更简单
- ES6是前端发展趋势,就业必备技能
let
- 声明变量
// 声明变量
let a;
let b,c;
let e = 100;
let f = 100, g = 200,h = [];
- 变量不能重复声明
- 块级作用域
只在代码块里有效 - 不存在变量提升
console.log(name); // undefined
var name = "qiu";
console.log(name); // 报错
let name = "qiu";
- 不影响作用域链
const
- 声明常量
// 声明常量
const AGE = 18;
console.log(AGE);
- 一定要赋初始值
- 一般常量使用大写
- 常量值不能修改
- 块级作用域
- 对于数组和对象的元素修改,不算做对常量的修改,不会报错(引用地址并没有变)
变量解构赋值
允许直接从数组和对象中提取值并赋值
- 数组的解构
const hobby = ["吃","喝","玩","乐"];
let [h1,h2,h3,h4]= hobby;
console.log(h1); //"吃"
console.log(h2); //"喝"
console.log(h3); //"玩"
console.log(h4); //"乐"
- 对象的解构
const person = {
name: "Peter",
age: 12,
sleep(){
console.log("zzzzzzzz");
}
}
let {name, age, sleep} = person;
模板字符串
- 声明
// 模板字符串
let str = `模板字符串`
- 内容中可以直接出现换行符
let str2 = `<ul><li>苹果<li><li>香蕉<li><ul>`;
- 变量拼接
const fruits = ["苹果","香蕉","橘子","梨"];
let str3 = `我喜欢吃${fruits[2]}`;
对象简化写法
// 对象简化写法
let name = "lisa";
let sex = 1;
const student = {
name,
sex
}
箭头函数
// 箭头函数
let fn = (a,b) =>{
return a + b;
}
特性:
- this是静态的,this始终指向函数声明时所在作用域下的this值 (没有自己的this,指向外部this)
let getName = ()=>{
console.log(this.name);
}
function getName2() {
console.log(this.name);
}
window.name = "window";
const school = {
name:"TUST",
}
getName(); //"window"
getName2(); //"window"
getName.call(school); //"window"
getName2.call(school); //"TUST"
- 不能作为构造函数实例化对象
- 不能使用arguments变量
- 箭头函数的简写
1)当形参有且只有一个的时候,可以省略小括号
let add = n => {
return n + 1;
}
2)当代码题只有一条语句的时候,可以省略花括号
此时return也必须省略,且语句的执行结果就是函数的返回值
let add = n => n + 1;
函数参数的默认值
- 一般把有初始值的形参放到最后
// 允许给函数参数赋值初始值
function add(a,b,c = 10) {
return a + b + c;
}
add(1,3); //14
- 与结构赋值结合使用
// 结合结构赋值使用
functionconnect({host, username, pass, port=3306}) {
console.log(host, username, pass, port);
}
connectInfo = {
host: "localhost",
username: "root",
pass: "root",
port: 8080
}
connect(connectInfo);
rest参数
用于获取函数的实参,同来代替arguments
与arguments不同的是,arguments是对象,rest是数组
有多个rest参数必须放到最后function date(a,b,...args){}
function date(...args){
console.log(args); // ['苹果', '香蕉', '橘子', '梨']
}
date("苹果","香蕉","橘子","梨");
扩展运算符
将数组转换为逗号分隔的参数序列
const fruits = ['苹果', '香蕉', '橘子', '梨'];
date(...fruits); // 等同于date("苹果","香蕉","橘子","梨");
Symbol
Symbol特点
- Symbol的值是唯一的,用来解决命名冲突的问题
- Symbol值不能与其他数据进行运算
- Symbol定义的对象属性不能使用for…in循环遍历,但是可以使用Reflect.ownKeys来获取对象的所有键名
let s = Symbol();
console.log(s,typeof s); //Symbol() 'symbol'
迭代器
工作原理
- 创建一个指针对象,指向当前数据结构的起始位置
- 第一次调用对象的next方法,指针自动指向数据结构的第一个成员
- 接下来不断调用next方法,指针一直往后移动,直到指向最有一个成员
- 每调用next方法返回一个包含value和done属性的对象
注:需要自定义遍历数据的时候,要想到迭代器
原生具备iterator接口的数据(可用for of 遍历)
Arrary、Arguments、Set、Map、String、TypedArray、NodeList
const fruits = ['苹果', '香蕉', '橘子', '梨'];
let iterator = fruits[Symbol.iterator](); //获取迭代器对象
console.log(iterator.next()); //{value: '苹果', done: false}
console.log(iterator.next()); //{value: '香蕉', done: false}
console.log(iterator.next()); //{value: '橘子', done: false}
console.log(iterator.next()); //{value: '梨', done: false}
console.log(iterator.next()); //{value: 'undefined', done: true}
生成器函数与调用
生成器其实就是一个特殊的函数
function * gen(){
console.log("Hello generator");
yield "abcdefg"; //可以看成函数分隔符
//-----------------------------------------
console.log("How are you?");
yield "hijklmn";
//-----------------------------------------
console.log("I am fine. Thank you!");
let str = yield "opqrst";
//-----------------------------------------
console.log(str);
}
let iterator = gen();
// console.log(iterator); //gen {<suspended>}
iterator.next(); //Hello generator
console.log(iterator.next()); //How are you? {value: 'hijklmn', done: false}
iterator.next(); //I am fine. Thank you!
iterator.next("Bye bye"); //Bye bye
Promise
介绍与基本用法
const p = new Promise(function(resolve, reject){
setTimeout(function(){
// 成功情况
// let data = "数据库中数据";
// resolve(data); //执行成功回调
// 失败情况
let msg = "网络连接失败";
reject(msg); //执行失败回调
},1000)
})
// 调用Promise对象的then方法a
p.then(function(data){
console.log("成功回调!!!",data);
},function(error){
console.log("失败回调。。。。。",error);
})
Promise封装读取文件
const fs = require('fs');
const p = new Promise(function(resolve, reject){
fs.readFile("./resources/readme.txt",(err,data)=> {
// 如果失败,则执行错误回调
if (err) reject(err);
// 如果成功,则执行成功回调
resolve(data);
});
})
p.then(function(value){
console.log(data.toString());
},function(reason) {
console.log("获取失败",reason);
})
Promise.prototype…then方法
之前的例子
const p = new Promise(function(resolve, reject){
setTimeout(function(){
// 成功情况
// let data = "数据库中数据";
// resolve(data); //执行成功回调
// 失败情况
let msg = "网络连接失败";
reject(msg); //执行失败回调
},1000)
})
// 调用Promise对象的then方法
p.then(function(data){
console.log("成功回调!!!",data);
},function(error){
console.log("失败回调。。。。。",error);
})
p.then方法返回的是一个Promise对象,对象中有两个是,一个是PromiseState
一个是PromiseResult
这两个属性,根据回调内容不同而不同
// 调用Promise对象的then方法
let pThen =p.then(function(data){
console.log("成功回调!!!",data);
// 1. 返回非Promise类型值,PromiseState为fulfilled,PromiseResult为undefined
// return data;
// 2. 返回非Promise类型值,PromiseState为该Promise的成功或失败结果,PromiseResult为结果参数
// return new Promise(function(resolve,reject){
// resolve(123)
// })
// 3. 抛出错误,PromiseState为rejected,PromiseResult为抛出的错误
throw "err";
},function(error){
console.log("失败回调。。。。。",error);
})
console.log(pThen);
比如,此时结果就如下
可以通过在then中返回Promise进行链式调用,杜绝回调地狱问题
Promise.catch方法
就相当于then方法,不写第一个回调
p.catch(function(reason) {
console.warn(reson);
})
Set
自动去重
// Set
let s= new Set(["苹果","香蕉","橘子","梨","橘子"]);
console.log(s); //Set(4) {'苹果', '香蕉', '橘子', '梨'}
// 元素格式
s.size;
// 添加元素
s.add("葡萄");
// 删除元素
s.delete("橘子");
// 检测
s.has("西瓜");
// 清空
s.clear();
// 循环 实现了iterator迭代器接口可以用forof
for (const iterator of s) {
console.log(iterator);
}
Map
键值对集合
// Map
let m =new Map();
// 添加元素
m.set("name","qiu");
m.set({name:"qiu"},{obj:null});
// 键值对个数
m.size;
// 获取
m.get("name");
// 删除
m.delete("name");
// 清空
m.clear();
// 遍历 实现了iterator接口
for (const iterator of m) {
console.log(m);
}
class类
介绍与初体验
对比一下ES5和ES6创建实例对象
// class
// ES5
function Phone(brand, price){
this.brand = brand;
this.price = price;
}
// 通过原型对象添加方法
Phone.prototype.open = function(){
console.log("dangdangdangdang~");
}
// 实例化对象
let Huawei = new Phone('华为',5999);
// ES6
class Phone {
// 构造方法 名字不能修改
constructor(brand, price){
this.brand = brand;
this.price = price;
}
// 方法 不能使用open: function(){}形式
open(){
console.log("dangdangdangdang~");
}
}
let Vivo = new Phone("Vivo",3999);
静态成员
属于类的属性,不属于实例对象
class Phone {
// 静态成员
static classify = "数码设备";
}
类的继承
ES5中的构造函数继承(父级就不写了,和上面一样)
// ES5
function AIPhone(brand, price, color, os) {
Phone.call(this,brand,price);
this.color = color;
this.os = os;
}
// 设置子级构造函数的原型
AIPhone.prototype = new Phone;
AIPhone.prototype.constructor = AIPhone;
ES6中类的继承
// ES6
class AIPhone extends Phone {
constructor(brand, price, color, os) {
super(brand,price); //父类构造函数
this.color = color;
this.os = os;
}
}
重写
重写同名方法,当重写方法中不允许调用父类方法,只能直接覆盖
get和set
class Phone {
// 构造方法 名字不能修改
constructor(brand, price){
this.brand = brand;
this.price = price;
}
get color() {
console.log("读取了color属性");
return "黑色";
}
set color(newVal) {
console.log("修改了color属性");
// this.color = newVal;
}
}
let vivoS9 = new Phone("Vivo",3999);
console.log(vivoS9.color);
vivoS9.color = "白色";
console.log(vivoS9.color);
ES6的数值扩展
Number.EPSILON
是js表示的最小精度- 二进制和八进制:二进制
0bxxx
八进制0oxxx
十进制xxx
十六进制0xxxx
Number.isFinite
检测是否为有限数Number.isNaN
检测数值是否为NaNNumber.parseInt
和Number.parseFloat
字符串转为数字(整数/浮点数)Number.isInteger
判断是否为整数Math.trunc
将数字的小数部分抹掉Math.sign
判断一个数到底为正数(1)、负数(-1)还是零(0)
对象方法扩展
Object.is
判断两个值是否完全相等(与===的区别NaN===NaN
为false)Object.assign
两个对象的合并(相同的覆盖,不同的保留)Object.setPrototypeOf
设置原型对象Object.getPrototypeOf
获取原型对象 (不建议使用)
模块化
将大文件拆分为多个小文件,再组合
优点:
- 防止命名冲突
- 代码复用
- 高维护性
主要有两个命令构成:export
暴露和import
引用
//test.js
// 分别暴露
export let school = "TUST";
export let add = "TJ";
//统一暴露
let school = "TUST"
let add = "TJ"
export {school, add}
// 默认暴露
export default {
school: "TUST",
add: "TJ"
}
//study.html
//<script type="module">
//通用引入方式
import * as text from "./text.js";
// 解构赋值形式
import {school, add as address} from "./text.js"; //分别暴露 重名用as取别名
import {default as text} from "./text.js"; //统一暴露 必须取别名
// 简便形式 只能对应默认暴露
import text from "./text.js";
还可以直接在标签上引用 (应该是vue中拆分出js文件)(一般不这么直接引,会有兼容问题)
<script src="./text.js" type="module">
在项目中,一般是需要使用工具将代码进行转换并打包,再通过标签引用来实现模块化
引入NPM包
- 通过
npm i xxx
命令安装 - 通过
import 变量名 from "包名";
引入