一、ECMAScript相关介绍
1.1什么是ECMA
ECMA(European Computer Manufactruers Association)中文名称为欧洲计算机制造协会。这个组是的目标是评估、开发和认可电信和计算机标准。
1.2、什么是ECMAScript
ECMAScript是由Ecma国籍通过ECMA-262标准化的脚本程序设计语言。
1.3什么是ECMA-262
Ecma国际制定了很多标准,ECMA-262只是其中一个
1.4为什么要学习ES6
(1)ES6的版本变动内容最多,具有里程碑意义
(2)ES6加入许多新的语法特征,编程实现更简单,高效
(3)ES6是前端发展趋势,就业必技能
二、let变量声明以及声明特征
1、变量不能重复声明
2、块级作用域(if else while for)全局 函数 eval
3、不存在变量提升
4、不影响作用域链
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script>
声明变量
let a;
let b,c,d;
let e = 100;
let f=432,g='fdsf',h=[];
1、变量不能重复声明
let star = "赵丽颖";
let star = "花千骨";
2、块级作用域(if else while for) 全局 函数 eval
{
let girl = "小青";
}
console.log(girl);
3、不存在变量提升
console.log(per);
let per = "花千骨";
4、不影响作用域链
{
let school = "北京大学";
function f1() {
console.log(school);
}
f1();
}
</script>
let经典案例实现
<!DOCTYPE html>
<style>
.page-header {
border-bottom: 1px solid darkgray;
}
.item {
width: 100px;
height: 50px;
border: 1px solid lightseagreen;
float: left;
margin-right: 20px;
margin-top: 30px;
}
</style>
<div class="container">
<h2 class="page-header">点击切换颜色</h2>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
<script>
let itemObj = document.getElementsByClassName("item");
for (let i=0;i<itemObj.length;i++){
itemObj[i].onclick = function () {
itemObj[i].style.backgroundColor = "pink";
}
}
</script>
三、const声明常量以及特点
1、一定要赋初始值
2、一般常量使用大写
3、常量的值不能修改
4、块级作用域
5、对于数组和对象的元素修改,不算做对常量的修改,不会报错
<script>
声明常量
const SCHOOL = "北京大学";
const TEAM = ['uzi','akm','m416','awm'];
TEAM.push('vector');
</script>
四、变量解构赋值
ES6允许按照一定模式从数组和对象中提取值,对变量进行赋值,这被称为解构赋值。
1、数组的解构
2、对象的解构
<script>
1、数组的解构
const F4 = ['刘能','赵四','宋小宝'];
let [liu,zhao,song] = F4;
console.log(liu);
console.log(zhao);
console.log(song);
2、对象的解构
const zhao1 = {
name:'赵本山',
age:12,
xiaopin:function () {
console.log("我能演小品");
}
};
let {name,age,xiaopin} = zhao1;
console.log(name);
console.log(age);
console.log(xiaopin);
</script>
五、模板字符串
ES6引入新的声明字符串的方式``(反引号)
1、内容中可以直接出现换行符
2、变量拼接${}
<script>
1、声明
let str = `我是一个字符串`;
console.log(str);
2、内容中可以直接出现换行符
let str1 = `<ul>
<li>沈腾</li>
<li>沈腾</li>
<li>沈腾</li>
`
3、变量拼接${}
let love = "沈腾";
let out = `${love}是最搞笑的明星`;
console.log(out);
</script>
六、对象的简化写法
ES6允许在大括号里面。直接写入变量和函数值,作为对象的属性和方法。这样书写更加简洁。
<script>
let name = "北京";
let change = function () {
console.log("你好");
}
const school ={
name,
change,
import(){
console.log("嘿嘿");
}
}
console.log(school);
</script>
七、箭头函数以及声明特点
ES6 允许使用 =>(箭头函数) 定义函数
1、this 是静态的,this始终指向函数声明时所在作用域下的this的值
2、不能作为构造函数实例化对象
3、不能使用arguments变量
4、箭头函数的简写
(1)省略小括号,当形参有且只有一个的时候
(2)省略花括号,当代码只有一条语句的时候,此时return必须省略,而且语句的执行结果就是函数的返回值。
<script>
let fn = (a,b) => {
return a+b;
}
let fn1 = fn(1,2);
console.log(fn1);
1、this 是静态的。this 始终指向函数声明时所在作用域下的this的值
function getName() {
console.log(this.name);
}
let getName2 = () => {
console.log(this.name);
}
设置window对象的name属性
window.name = '北京';
const school = {
name:"beijing"
}
直接调用
getName();//北京
getName2();//北京
call方法调用
getName.call(school);//beijing
getName2.call(school);//北京
2、不能作为构造函数实例化对象
let Person = (name,age) => {
this.name = name;
this.age = age;
}
let me = new Person('xiao',12);
console.log(me);
3、不能使用arguments变量
let fn = () => {
console.log(arguments);
}
fn(1,2,3);
4、箭头函数的简写
1)省略小括号,当形参有且只有一个的时候
let add = n =>{
return n+n;
}
console.log(add(9));
2)省略花括号,当代码只有一条语句的时候,此时return必须省略
而且语句的执行结果就是函数的返回值
let pow =n => n*n;
console.log(pow(9));
</script>
箭头函数适合与this无关的回调 ,定时器 数组的方法回调
箭头函数不适合与this 有关的回调 事件回调 对象的方法
<style>
div {
width: 200px;
height: 200px;
background-color: #5588aa;
}
</style>
<div id="ad"></div>
<script>
需求-1 点击div 2s后变成粉色
let ad = document.getElementById("ad");
ad.addEventListener("click",function () {
//保存 this 的值
//let _this = this;
//定时器
setInterval(() => {
//修改背景颜色
//_this.style.backgroundColor = "pink";
this.style.backgroundColor = "pink";
},2000);
});
需求-2 从数组中返回偶数的元素
const arr =[1,3,5,6,8,9];
const result = arr.filter(item => item % 2 === 0);
console.log(result);
</script>
八、箭头函数与普通函数的区别
1、this指向问题
(1) 箭头函数的this指向的是父级作用域的this,是通过查找作用域链来确定 this 的值,也就是说,看的是上下文的this,指向的是定义它的对象,而不是使用时所在的对象;普通函数指向的是它的直接调用者。
(2) 箭头函数没有this,它的this是继承来的,默认指向定义它的时候的对象,就是我们说的宿主对象,而不是执行它的对象。
(3)我们不可以用 call()、apply()、bind() 这些方法去改变this的指向。
2、不可以被当做构造函数
不能被当作构造函数来使用,通过new命令来作为构造函数会报错,这里没有构建原型的说法,不存在prototype这个属性,也不能通过super访问原型的属性,而且new target也是不能用的
3、不可以使用arguments对象,该对象在函数体内不存在,如果要用就用rest参数替代。
4、不可以使用yield命令,因此箭头函数不能用作 Generator 函数。
5、不适用场合
(1)定义对象的方法,且该方法内部包括this时。
(2)需要动态this的时候,也不应使用箭头函数。
const cat = {
lives: 9,
jumps: () => {
this.lives--;
}
}
九、函数参数的默认值设置
ES6允许给函数参数赋值初始值
1、形参初始值,具有默认值的参数,一班位置要靠后(潜规则)
2、与解构赋值结合
<script>
1、形参初始值,具有默认值的参数,一般位置要靠后(潜规则)
function add(a,b,c=10) {
return a+b+c;
}
let result = add(1,2);
console.log(result);
2、与解构赋值结合
function connect(name,username,password,port) {
console.log(host);
console.log(username);
console.log(password);
console.log(port);
}
connect({
name:'localhost',
username:'root',
password:'root',
port:'3306'
})
</script>
十、rest参数
ES6引入rest参数,用于获取函数的实参,用来代替arguments
1、rest参数必须要放到参数最后
<script>
ES6获取实参的方式
function date() {
console.log(arguments);
}
date("张三","李四","王五");
rest参数
function date(...args) {
console.log(args);
}
date("张三","李四","王五");
rest参数必须要放到参数最后
function f(a,b,...args) { }
</script>
十一、扩展运算符的介绍
… 扩展运算符 能将【数组】转换为逗号分隔的【参数序列】
<script>
声明一个数组
const tfboys = ["易烊千玺","王源","王俊凯"];
声明一个函数
function chunwan() {
console.log(arguments);
}
chunwan(tfboys); //length=1
chunwan(...tfboys); //length=3
</script>
扩展运算符的应用
<div></div>
<div></div>
<div></div>
<script>
数组的合并
const temp1 = ['11','22'];
const temp2 = ['33','44'];
const temp = [...temp1,...temp2];
console.log(temp);
数组的克隆
const arr = ['张三','李四','王五'];
const arr1 = [...arr];
console.log(arr1); //['张三','李四','王五']
将伪数组转为真正的数组
let dv = document.querySelectorAll("div");
const divArr = [...dv];
console.log(divArr);
</script>
十二、Symbol的介绍与创建
**1、Symbol:**ES6引入了一种新的原始数据类型Symbol,表示独一无二的值。它是javaScript语言的第七种数据类类型,是一种类似于字符串的数据类型。
2、Symbol特点:
(1)Symbol的值是唯一的,用来解决命名冲突的问题
(2)Symbol值不能与其它数据类型进行运算
(3)Symbol定义的对象属性不能使用for…in循环遍历,但是可以使用Reflect.ownKeys来获取对象的所有键名。
3、Symbol不能进行计算
<script>
创建Symbol
let s = Symbol();
let s2 = Symbol('张三');
let s3 = Symbol('张三');
//Symbol.for 创建
let s4 = Symbol.for('张三');
let s5 = Symbol.for('张三');
console.log(s2==s3); //false
console.log(s2==s4); //false
console.log(s4==s5); //true
</script>
十三、对象添加Symbol类型的属性
<script>
let game;
声明一个对象
let method = {
up:Symbol(),
down:Symbol()
};
game[method.up] = function () {
console.log("我可以改变形状");
}
game[method.down] = function () {
console.log("我可以快速下降");
}
console.log(game);
第二种方式
let youxi = {
name:'狼人杀',
[Symbol('zibao')]:function () {
console.log("我可以发言");
},
[Symbol('say')]:function () {
console.log("自爆");
}
}
</script>
十四、Symbol的内置属性
作为对象的属性,用于扩展对象的功能的
Symbol.hasInstance
Symbol.isConcatSpreadable
Symbol.unscopables
Symbol.match
Symbol.replace
Symbol.search
Symbol.split
Symbol.iterator
Symbol.toPrimitive
Symbol.toStringTag
Symbol.species
<script>
class Person {
static [Symbol.hasInstance](param){
console.log(param);
console.log("我被用来检测类型了");
return false;
}
}
let o = {};
console.log(o instanceof Person);
const arr = [1,2,3];
const arr2 = [4,5,6];
arr2[Symbol.isConcatSpreadable] = false; //控制数组的值是否展开
console.log(arr.concat(arr2));
</script>
十五、迭代器
1、 迭代器(iterator)是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署Iterator接口,就可以完成遍历操作
2、Iterator接口:对象里面的一个属性
(1)ES6创造了一种新的遍历命令 for…of 循环,Iterator接口主要供for…of消费
(2)原生具备iterator接口的数据(可用for of遍历)
Array
Arguments
Set
Map
String
TypedArray
NodeList
3、工作原理:
(1)创建一个指针对象,指向当前数据结构的起始位置
(2)第一次调用对象的next方法,指针自动指向数据结构的第一个成员
(3)接下来不断调用next方法,指针一直往后移动,直到指向最后一个成员
(4) 每调用next方法返回一个包含value和done属性的对象
注意:需要自定义遍历数据的时候,要想到迭代器
<!DOCTYPE html>
<script>
声明一个数组
const arr = ['11','22','33','44'];
arr[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:[
'xiaoming',
'xiaoqiang',
'xiaodong'
],
[Symbol.iterator](){
//索引变量
let index = 0;
let _this = this;
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};
}
}
}
}
}
</script>
十六、生成器函数声明与调用
生成器函数是ES6提供的一种异步编程解决方案,语法行为与传统函数完全不同。
yield 函数代码的分隔符
<script>
function * gen() {
console.log(111);
yield '1';
console.log(222);
yield '2';
console.log(333);
yield '3';
console.log(444);
}
let iterator = gen();
iterator.next(); //111
iterator.next(); //222
for (let v of gen()){
console.log(v);
}
</script>
</body>
</html>
十七、生成器函数的参数传递
<script>
function * gen(args) {
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方法可以传入实参
console.log(iterator.next('BBB'));
console.log(iterator.next('CCC'));
console.log(iterator.next('DDD'));
</script>
生成器函数实例
<script>
/*
* 异步编程
* 1s 后控制台输出 111 2s 后输出 222 3s后输出 333
* */
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>
十八、Promise
promise是ES6引入的异步编程解决方案。语法上Promise是一个构造函数,用来封装异步操作并可以获取其成功后失败的结果
(1)Promise构造函数:Promise(excutor){}
(2)Promise.prototype.then方法
(3)Promise.prototype.catch方法
<script>
//实例化Promise对象
const p = new Promise(function (resolve,reject) {
setTimeout(function () {
// let data = '数据库中的用户数据';
// resolve(data); //对象状态 成功
let err = '数据读取失败';
reject(err);
},1000)
});
//调用promise对象的then方法
p.then(function (value) { //成功
console.log(value); //数据库中的用户数据
},function (reason) { //失败
console.error(reason);
})
</script>
十九、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.log(reason);
})
</script>
二十、Promise.prototype.then方法
<script>
//创建Promise对象
const p = new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve('用户数据');
},1000)
})
调用then方法 then方法的返回结果是Promise 对象,对象状态由回调函数的执行结果决定
如果回调函数中返回的结果是 非Promise类型的属性,状态为成功,返回值为对象的成功的值
p.then(value => {
console.log(value);
},reason => {
console.warn(reason);
})
</script>
二十一、Promise对象catch方法
<script>
const p = new Promise((resolve,reject)=>{
setTimeout(()=>{
reject("出错啦")
},1000)
})
/*p.then(function (value) {
console.log(value);
},function (reason) {
console.log(reason);
})*/
p.catch(function (reason) {
console.warn(reason);
})
</script>
二十二、Set
1、 ES6 提供了新的数据结构 Set(集合)。它类似于数组。但成员的值都是唯一的,集合实现了iterator接口,所以可以使用 扩展运算符 和 for…of… 进行遍历.
2、集合的属性和方法:
(1)size 返回集合得元素个数
(2)add 增加一个新元素,返回当前集合
(3)delete 删除元素,返回boolean值
(4)has 检测集合中是否包含某个元素,返回boolean值
<script>
let s = new Set();
let s2 = new Set(['111','222','333','444','111']); //自动去重
//元素个数
console.log(s2.size); //4
//添加新元素
console.log(s2.add('555'));
//删除元素
console.log(s2.delete('222')); //true
//是否包含某个元素
console.log(s2.has('123')); //false
//清空集合
//console.log(s2.clear());
console.log(s2);
for (let v of s2){
console.log(v);
}
</script>
<script>
let arr = [1,2,3,4,5,4,3,2,1];
1、数组去重
let result = [...new Set(arr)];
console.log(result);
2、交集
let arr2 = [4,5,6,5,6];
let result1 = [...new Set(arr)].filter(item=>{
let s2 = new Set(arr2); //4,5,6
if (s2.has(item)){
return true;
}else{}
return false;
})
console.log(result1);
3、并集
let union = [...new Set([...arr, ...arr2])];
console.log(union);
4、差集
let result2 = [...new Set(arr)].filter(item=>{
let s2 = new Set(arr2); //4,5,6
if (s2.has(item)){
return false;
}else{}
return true;
})
console.log(result2);
</script>
二十三、Map
1、ES6提供了Map数据结构。它类似于对象,也是键值对的集合。
2、各种类型的值(包括对象)都可以当做键.
3、Map也实现了iterator接口,所以可以使用(扩展运算符)和(for…of)进行遍历
4、Map的属性和方法:
(1) size 返回Map的元素个数
(2) set 增加一个新的元素,返回当前Map
(3)get 返回键名对象的赋值
(4) has 检测Map中是否包含某个元素,返回boolean值
(5) clear 清空集合 ,返回undefined
<script>
let m = new Map();
m.set("name","张三");
console.log(m);
</script>
二十四、Class类
1、ES6提供了更接近传统语言的写法,引入了class类这个概念,作为对象的模板。
2、通过class关键字,可以定义类。
3、新的class写法只是让对象原型的写法更加清晰,更像想想对象变成的语法而已。
4、 知识点:
(1)class声明类
(2)constructor定义构造函数初始化
(3)extends继承父类
(4)super调用父级构造方法
(5)static定义静态方法和属性
(6)父类方法可以重写
class静态成员
<script>
class Phone{
static 标识的方法属于类而不属于实例对象
静态属性
static name = "手机";
static change(){
console.log("我可以改变世界");
}
}
let nokia = new Phone();
console.log(nokia.name); //undefined
console.log(Phone.name); //手机
</script>
构造函数继承
<script>
手机
function Phone(brand,price) {
this.brand = brand;
this.price = price;
}
Phone.prototype.call = function () {
console.log("我可以发电话");
}
智能手机
function SmartPhone(brand,price,color,size) {
Phone.call(this,brand,price);
this.color = color;
this.size = size;
}
设置子集构造函数的原型
SmartPhone.prototype = new Phone();
SmartPhone.prototype.constructor = SmartPhone;
声明子类的方法
SmartPhone.prototype.photo = function () {
console.log("我可以拍照");
}
SmartPhone.prototype.playGame = function () {
console.log("我可以大欧系");
}
const chuizi = new SmartPhone("锤子",2111,"pink","14");
console.log(chuizi);
</script>
class的类继承
<script>
class Phone{
构造方法
constructor(brank,price) {
this.brand = brank;
this.price = price;
}
父类的成员属性
call(){
console.log("我可以打电话");
}
}
class SmartPhone extends Phone{
构造方法
constructor(brand,price,color,size) {
super(brand,price); //Phone.call(this,brand,price)
this.color = color;
this.size = size;
}
子类可以重写父类的构造方法,但是不可以直接调用
call() {
console.log("我可以视频通话");
}
photo(){
console.log("我可以拍照");
}
playGame(){
console.log("我可以打游戏");
}
}
const xiaomi = new SmartPhone("小米",1223,"pink","2.1");
xiaomi.playGame();
</script>
class中getter和setter设置
<script>
class Phone{
get price(){
console.log("价格属性被读取了");
}
set price(val){
console.log("价格属性被修改了");
}
}
实例化对象
let s = new Phone();
//console.log(s.price);
s.price = "free";
</script>
二十五、ES6的数值扩展
1、Number.EPSILON 是 JavaScript 表示的最小精度。EPSILON 属性的值接近于 2.22044…
2、二进制和八进制
3、Number.isFinite 检测一个数值是否为有限数
4、Number.isNaN 检测一个数值是否为NaN
5、Number.parseInt Number.parseFloat 字符串转整数
6、Number.isInteger 判断一个数是否为整数
7、Math.trunc 将数字的小数部分抹掉
8、Math.sign 判断一个是到底为正数、负数、还是零
二十六、ES6的对象方法扩展
1、Object.is 判断两个值是否完全相等
2、Object.assign 对象的合并
3、Object.setPrototypeOf设置原型对象 Object.getPrototypeOf
<script>
1、Object.is 判断两个值是否完全相等
console.log(Object.is(12,12)); //true
console.log(Object.is(NaN,NaN)); //true
console.log(Object.is(NaN===NaN)); //false
2、Object.assign 对象的合并
const config1 = {
name:'zhangsan',
age:'11'
}
const config2 ={
name: 'lisi',
age:'1122'
}
console.log(Object.assign(config1,config2)); //{name: 'lisi', age: '1122'}
3、Object.setPrototypeOf设置原型对象 Object.getPrototypeOf
</script>
二十七、模块化
1、模块化: 模块化是指将一个大的程序文件,拆分成许多小的文件,然后将小文件组合起来。
2、模块化的好处:
(1)防止命名冲突
(2)代码复用
(3)高维护性
3、模块化规范产品:
(1)CommonJS => NodeJS、Browserify
(2)AMD => requireJS
(3)CMD => seaJS
4、ES6模块化语法:
(1)export 命令用于规定模块的对外接口
(2)import 命令用于输入其他模块提供的功能
5、浏览器使用ES6模块化引入模块方式一:
6、浏览器使用ES6模块化引入模块方式二:
7、babel对ES6模块化代码转换
安装工具 babel-cli babel-preset-env browserify
企业一般使用:webpack