ES6--(ECMAScript第6版本);ES6是JavaScript的新标准。
一、ES新特性
1.var变量提升的问题
<script>
/* 任何被提升的东西都会被移动到顶部,需要注意:
移动到顶部的只是变量的声明,而不是所赋的值
*/
// 例一:
// var Uname; 会被解析成声明未赋值
console.log(Uname);
var Uname = 'zhangsan';
// ---------------------------------------------------------
// 例二:
function dome() {
console.log('dome ' + myName);
};
dome();
var myName = 'rainyjune';
// ----------------------------------------------------------
// 例三:
dome("zhangsan");
function dome(name) {
console.log("My name is " + name);
}
dome("zhangsan"); // My name is zhangsan
</script>
2.let 和 const
-
时间死区
-
let 和 const 声明变量,没有变量提升
<script>
// let 和 const '时间死区'
console.log(Uname);
const Uname = ' zhangsan ';
let Uname = ' zhangsan ';
</script>
let 和 const 是一个块级作用域
<script>
if(1 === 1) {
let a = 10;
}
console.log(a);
</script>
-
let 和 const 不能被重复声明
// let let a = 10; let a = 9; console.log(a); // const const b =20; const b =10; console.log(b);
-
const 声明的变量,一旦被声明,就无法再次修改 (通常使用const来定义常量)
const max = 20; max = 25; console.log(max);
-
let 和 const 不会污染全局变量
let RegExp = 10; console.log(window.RegExp); console.log(RegExp);
-
建议在实际开发中,不使用var来声明变量,在默认情况下使用const来声明,当我们自己知道有需要改变的变量时,才使用let
3.模板字符串
-
模板字符串采用: 反引号的形式包裹,插入变量时使用${变量名}插入
<script> /* 模板字符串采用: 反引号的形式包裹, 插入变量时使用${变量名}插入 */ const person = { username: 'zhangsan', age: 20, sex: '男' }; // 一般模式输出 const echo = '我的名字是:' + person.username + '今年' + person.age + '岁了' + '性别:' + person.sex; console.log(echo); // 使用模板字符串输出 const echo = `我的名字是:${person.username}, 今年${person.age}岁了,性别:${person.sex}`; console.log(echo); </script>
4.函数默认值---剩余参数
-
剩余参数采用了:...具名的形式
-
剩余参数的出现解决了arguments的问题
-
需要注意的是,剩余参数必须写在后面
-
剩余运算符:把多个独立的合并到一个数组中
function show(obj, ...keys) { let result = {}; for (let i = 0; i < keys.length; i++) { result[keys[i]] = obj[keys[i]]; } return result; } let dome = { name: 'sisi', age: 20, sex: '男' } let dome1 = show(dome, 'name', 'age', 'sex'); console.log(dome1);
5.扩展运算符
-
扩展运算符:将一个数组分隔,并将各个项分离的参数传递给函数
// 扩展运算符 , 采用...具名参数的方式 const arr = [12, 32, 24, 52, 35, 645, 324, 54]; // es5 获取最大值语法 console.log(Math.max.apply(null, arr)); // es6 扩展运算符语法 console.log(Math.max(...arr));
6.箭头函数
-
写法: 采用了( ) => ({ });
// 箭头函数 let fn = (a, b) => (a + b); console.log(fn(10, 20));
-
箭头函数的this指向:箭头函数没有this指向吗,箭头函数内部的this只用通过查找作用域链的方式查找;
-
箭头函数内部的this指向的是它的父级,如果没有父级,则默认为window;
-
箭头函数不能使用new关键字来实例化对象;
-
箭头函数内部没有arguments,因为箭头函数没有作用域链
// 箭头函数 let fn = (a, b) => (a + b); console.log(fn(10, 20)); // 对象 let getObject = id => ({ id: id, name: '张三' }); let obj = getObject(1); console.log(obj); // 闭包 let fun = (() => { return () => { console.log('hello world'); } })(); fun();
-
7.解构赋值
-
解构赋值是对赋值运算符的一种扩展,
-
解构赋值针对数组或对象来进行操作,
-
使用赋值运算符可以节省代码量
-
<script> // 完全解构 let node = { type: 'inder', id: 2, name: '李四' } // 初始方法 let type = node.type; let id = node.id; let name = node.name; console.log(type,id,name); // es6解构赋值 // let {type,id, name} = node; // console.log(type,id,name); // 不完全解构,可忽略 let obj = { a: { name: '张三' }, b: [], c: 'hello world' } let {a} = obj; console.log(a); // 剩余运算符 let obj1 = { d: { name: '张三' }, e: [], f: 'hello world' } let {d,...keys} = obj; console.log(keys); // 对数组解构 let arr = [1,2,3]; let [a1,b2] = arr; console.log(a1,b2); // 可嵌套 let [aa,[bb],cc] = [1,[2],3]; console.log(aa,[bb],cc); </script>
8.扩展的对象功能
8-1.is()
-
is()对象----- 比较两个值是否严格相等
-
<script> // is() ---比较两个值是否严格相等 console.log(Object.is(NaN, NaN)); // true </script>
8-2.assign()
-
assign()对象 -- 对象合并
-
<script> // assign() -- 对象的合并 let newObj = Object.assign({}, { a: 1 }, { b: 2 }); console.log(newObj); //{a: 1, b: 2} </script>
9.Symbol数据类型
9-1.Symbol基本用法:
-
Symbol属于原始数据类型,表示独一无二的值
-
Symbol的最大用途是: 用来定义对象的私有变量
-
用Symbol定义的对象中的变量,取值时一定要用[变量名]
-
<script> let name = Symbol('sisi'); let name1 = Symbol('sisi'); // 判断以上两个变量是否相同 console.log(name === name1); // false let ss = Symbol('ss'); let obj = {}; // 使用Symbol定义对象中的变量,取值一定要用[变量名],否则获取不到 obj[ss] = '太憨傻'; console.log(obj[ss]); </script>
10.Set类型
-
Set是一种有序列表并且它的值没有重复;
-
Set的创建,必须使用实例化的形式来创建
let set = new Set()
-
创建、添加、删除、效验、查看元素:
<script> // set , 表示无重复的有序列表 let set = new Set(); // 添加元素 set.add(1); set.add(2); set.add([1, 3, 4]); console.log(set); // Set(3) {1, 2, Array(3)} // 删除元素 set.delete(2); console.log(set); // Set(2) {1, Array(3)} // 清除set中所有的数据 set.clear() console.log(set); //Set(0) {size: 0} // 效验某个值是否在set中 let s = set.has(2) console.log(s); // false let a = set.has(1); console.log(a); // true // 检查set中有多少项值 console.log(set.size); </script>
11.Map类型
-
Map类型是键值对的有序列表,键和值是任意类型
-
Map的创建方式:
let map = new Map()
-
可以使用set()方法传入key 和 value 来添加数据,使用get()方法传入key 获取当前项数据
-
<script> /* 1. Map类型是键值对的有序列表,键和值是任意类型 2. Map的创建方式: - 如:**let map = new Map()** 3. 可以使用set()方法传入key 和 value 来添加数据,使用get()方法传入key 获取当前项数据 */ let map = new Map(); // 添加 map.set('name', 'zhang'); map.set('age', 20); console.log(map); // 获取 console.log(map.get('name')); // 检查是否存在 console.log(map.has('name')); // 删除 console.log(map.delete('age')); // 清除 map.clear(); console.log(map); </script>
12.数组的扩展功能
12-1.from()方法
-
from()用于通过拥有length属性的对象或可迭代的对象来返回一个数组;
-
语法:
Array.from(object,mapFunction,thisvalue) // object: 要转换成数组的对象 // mapFUnction: 数组中每个元素要调用的函数 // thisvalue: 设置mapFunction中的this对象
-
<script> function add() { // 将类数组对象(arguments)生成数组 let arr = Array.from(arguments); console.log(arr); } add(1, 2, 3); // [1,2,3] let lis = document.querySelectorAll('li'); console.log(Array.from(lis)); console.log(Array.from(lis, el => el.textContent)); </script>
12-2.of()方法
-
of()将任意的数据类型,转换成数组
console.log(Array.of(3, 3, 1, 1, 4, 6)); // [3,3,1,1,4,6]
12-3.copywithin()
-
copywithin() 数组内部将指定位置的元素复制到其他的位置,返回当前数组
-
// target 复制到指定的位置 // start 起始位置 // end 结束位置 array.copyWithin(target, start, end)
-
<script> // copywithin // 就是将数组内部指定位置的元素复制到其他的指定位置 let array = [1, 2, 3, 4, 5, 6, 7]; let arr = array.copyWithin(0, 4); console.log(arr); // [5,6,7,4,5,6,7] </script>
12-4.find() 和 findIndex()
-
find()
-
find()查找数组中符合条件的数组中的第一个元素
-
<script> // find // 查找数组中符合条件的数组中的第一个元素 let num = [1, 2, 3, 4, 5, 6, 33, 22]; let num1 = num.find(n => n < 5) console.log(num1); // 1 </script>
-
-
findIndex()
-
findIndex()查找数组中符合条件的第一个元素的索引
-
<script> // findIndex // 查找数组中符合条件的第一个元素的索引 let sum = [1, 2, 3, 4, 5, 6, 33, 22]; let sum1 = sum.findIndex(n => n < 5) console.log(sum1); // 0 </script>
-
13.数组遍历的扩展
-
entries()----对键值对遍历
-
keys()-----对键遍历
-
values()-----对值遍历
<script> // kys() 对键进行遍历 for (let index of ['a', 'b', 'c'].keys()) { console.log(index); // 0 1 2 } // values() 对值进行遍历 for (let key of ['a', 'b', 'c'].values()) { console.log(key); // a b c } // entries() 对键值对的遍历 for (let ele of ['a', 'b', 'c'].entries()) { console.log(ele); } </script>
-
includes()---表示某个数组是否包含给定的值(返回布尔值)
-
includes()解决了 之前indexOf()的问题,可以更好的判断某个值是否在当前的数组中
<script> console.log([112, 2, 3, 4, 1].indexOf(1)); // 返回的是索引 console.log([112, 2, 3, 4, 1].indexOf('1')); // 不存在返回-1 console.log([1, 2, 3, 4].includes(2)); // true console.log([1, 2, 3, 4].includes('2')); // false </script>
-
14.迭代器Iterator
-
Iterator 是一种新的遍历机制,两个核心:
-
迭代器是一个接口,能快捷的访问数据,通过Symbol.inerator来创建迭代器, 通过迭代器的next()来获取迭代之后的结果;
-
迭代器是用于遍历数据结构的指针(相当于数据库的游标)
-
<script> // 迭代器Interator const items = ['si', 'zi', 'qq', 'ww']; const ite = items[Symbol.iterator](); console.log(ite.next()); console.log(ite.next()); console.log(ite.next()); console.log(ite.next()); console.log(ite.next()); // 当迭代不到指定的内容,则done为true </script>
-
15.生成器generator
-
generator和函数不同的是,generator由
`function*
定义(注意多出的*
号),并且,除了return
语句,还可以用yield
返回多次。 -
generator函数,可以通过yield关键字,将函数挂起,为了改变执行流提供了可能,同时也为了做异步编程提供了方案;
-
返回的是一个遍历器的对象,可以调用next()
<script> function* func() { console.log('one'); yield 2; console.log('two'); yield 3; console.log('end'); } // 返回一个遍历器对象,可以调用next let fn = func(); console.log(fn.next()); console.log(fn.next()); console.log(fn.next()); </script>
-
yield---停止执行, next----开始执行
-
iterator迭代器 和 generator生成器
-
回调地狱
<script> // 回调地狱 // 实现异步代码同步化 // yeild 和 next // 使用场景: 使用generator部署ajax function* load() { loadUi(); yield showLoad(); hideLoad(); } let ite = load(); ite.next(); function loadUi() { console.log(' 数据加载中......'); } function showLoad() { setTimeout(() => { console.log('数据加载完成'); ite.next() }, 2000) } function hideLoad() { console.log('隐藏数据加载'); } </script>
16.Promise对象
16-1.promise简介与基础
-
Promise--承诺:
-
是异步编程的一种解决方案,比传统的解决方案(回调函数)更加合理和更加强大
-
相当于一个容器,保存着未来才会结束的事件(异步操作)的一个结果
-
各种异步操作都可以用同样的方法进行处理(如:axios)
-
-
特点:
-
对象的状态不受外界的影响,处理异步操作的三种状态:
-
pending-----进行中
-
fulfilled(或resolved)-----已成功
-
rejected-----已失败
-
-
一旦状态改变,就不会再变,任何时候都可以得到这个 结果
-
-
promise基本用法:
// promise对象,解决异步操作 function timeOut(s) { return new Promise((resolved, rejected) => { setTimeout(() => { resolved('hello promise success!') }, s) }) } timeOut(2000).then((val) => { console.log(val); })
16-2.promise封装ajax
<script>
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.HeWeather6);
} else {
reject(new Error(this.statusText))
}
}
}
})
}
getJSON('https://free-api.heweather.net/s6/weather/now?location=beijing&key=4693ff5ea653469f8bb0c29638035976').then(
(val) => {
console.log(val);
}).then((error) => {
console.log(error);
})
</script>
16-3.then()方法
-
then() 实例状态发生改变时的回调函数;
-
then() 第一个参数是resolve回调函数,第二个是reject回调函数
-
then()返回的是一个新的promise实例,可以采用链式编程
16-4.resolve() 和 reject()方法
-
能将现有的任何对象转换成promise对象
16-5.all()方法
-
异步并行操作,一起操作执行
16-6.race()方法
-
某个异步请求设置超时时间,并且在超时后执行相应的操作
17.async异步操作
-
作用:使得异步操作更加方便
-
基本操作async会返回一个Pormise对象(有then 和 catch方法)
-
async是Generator的一个语法糖
-
async有 await等待方法
-
如果async函数中有多个await等待,那么then函数会等待所有的await等待执行完
二、面向对象编程
面向对象的优点:
-
模块化更深、封装性强
-
更容易实现复杂的业务逻辑
-
更易维护、易复用、易扩展
1.class类
1-1.类和对象开发步骤:
-
抽出对象的共同属性和行为,组成一个类;
-
对类进行实例化、获取类的操作;
1-2.类的基本语法:
-
在使用类创建对象时,需使用constructor 内置构造方法;
-
constructor 构造方法在使用类创建对象时会自动调用;
-
如果没有写constructor构造方法,程序会自动创建一个constrctor构造方法;
-
基本语法:
<script> // class类 --基本语法 class Person { // constructor 内置构造方法 // constructor 构造方法在使用类创建对象时会自动调用 // 如果没有写constructor构造方法,程序会自动创建一个constrctor构造方法 constructor(name) { this.name = name; } } // 利用类创建是实例化对象 let pe1 = new Person('冯春超'); let pe2 = new Person('张千帆'); console.log(pe1.name); console.log(pe2.name); </script>
-
类中的方法:
<script> // class类 --基本语法 class Person { // 构造方法 /* constructor 内置构造方法 constructor 构造方法在使用类创建对象时会自动调用 如果没有写constructor构造方法,程序会自动创建一个constrctor构造方法 */ constructor(name, age) { this.name = name; this.age = age } //方法 sayName() { // this代表了实例化对象 console.log('我叫:' + this.name); } sayAge() { console.log('我的年龄是:' + this.age); } } // 利用类创建是实例化对象 let pe1 = new Person('冯春超', 23); let pe2 = new Person('张千帆', 32); pe1.sayName() pe2.sayName() </script>
1-3.类的继承
-
类的继承:
-
是用来表示两个类之间的关系,子类可以继承父类中的属性和方法;
-
在继承之后,还可以添加自己所有的属性和方法;
-
-
继承关键字:
-
extends: 用于类的继承
// 继承类的语法 class 子类名 extends 父类 { constructor() { // ... } }
-
super:用于在类的继承时,访问父类中的方法或构造方法
// 继承类的语法 // super访问父类的方法 class 子类名 extends 父类 { constructor(x,y) { super(x,y) } }
-
继承案例:
<script> // 父类 class Father { constructor(name, age) { this.name = name; this.age = age; } say() { console.log(`我叫:${this.name},我今年${this.age}岁了`); } } // 子类 // extends 继承 class Son extends Father { constructor(name, age) { // super访问 super(name, age); } } let son1 = new Son('冯傻超', 23); console.log(son1); </script>
-
-
在继承中,写子类自己的方法
<script> // 父类 class Father { constructor(name, age) { this.name = name; this.age = age; } say() { console.log(`我叫:${this.name},我今年${this.age}岁了`); } } // 子类 // extends 继承 class Son extends Father { constructor(name, age, color) { // super访问 super(name, age); this.color = color; } // 独写子类的方法 sayColor() { return `我是${this.name},${this.age}岁了,皮肤颜色是${this.color}` } } let son1 = new Son('冯傻超', 23, '黄色'); console.log(son1.sayColor()); </script>
2.构造函数
1-1.构造函数的使用
-
构造函数主要用于创建对象,并为对象成员赋初始值;
-
可以把对象中的公共属性和方法抽取出来,封装到构造函数中
1-2.构造函数和类的区别
-
使用类创建对象,这些被创建的对象都是引用了同一个方法,可以节省空间;
-
使用构造函数创建的对象,并不能引用同一个方法
-
对比可知:
<script> // 构造函数 和 类的对比 // 类 class Person { song() { console.log('hello'); } } let p1 = new Person(); let p2 = new Person(); console.log(p1.song === p2.song); // true // 构造函数 function Student() { this.song = function () { console.log('hello'); } } let p1 = new Student(); let p2 = new Student(); console.log(p1.song === p2.song); // false </script>
1-3.prototype属性
-
prototype是构造函数中的属性;
-
prototype属性是用来访问原型对象的
1-4.__ proto __ 属性
-
如果不知道构造函数是哪个,可以使用__ proto __ 属性;
-
__ proto __ 属性是访问原型对象的;
1.5访问对象的构造函数
-
constructor属性: 通过实例对象的constructor属性可以访问实例对象的构造函数;
1-6.apply()和call()
-
apply(): 更改this指向,这个方法第二个参数是通过数组方式传递的;
-
call(): 更改this指向,这个方法第二个参数是通过传参方式传递的;
3.模块化管理
import:
-
是导入的意思,将外面的文件和数据导入到当前所需中
export:
-
是导出的意思,对外的接口,可以将现有数据导出