Day 81 ES6
ES6
var a = 2; var a = 5; console.log(a); // 5
let
1、let 声明变量,没有变量提升
console.log(b) // Uncaught ReferenceError: Cannot access 'b' before initialization let b = 3 console.log(b) # 3
2、是一个块作用域
if(1===1){ let c = 10; console.log(c) // 10 } console.log(c) // Uncaught ReferenceError: c is not defined
3、不能重复声明
let d = 10; let d = 20; console.log(d) // Uncaught SyntaxError: Identifier 'd' has already been declared
const
声明常量,一旦被声明,无法修改
const 声明变量,没有变量提升;是一个块作用域;不能重复声明
const max = 10; const max = 20; // Uncaught SyntaxError: Identifier 'max' has already been declared console.log(max)
const 可以修改常量内的值
const dit = { "name":'ysg' } dit.name='ysging' console.log(dit) // {name: "ysging"}
作用
作用一:for循环的经典例子
var arr = [] for (var i = 0; i < 10; i++) { arr[i] = function () { return i } } console.log(arr[5]()) // 10 const arr = [] for (let i = 0; i < 10; i++) { arr[i] = function () { return i } } console.log(arr[5]()) // 5
作用二:不会污染全局变量
var count = 10; console.log(count) // 10 console.log(window.count) // 10 let count = 10; console.log(count) // 10 console.log(window.count) // undefined 建议:一般情况下使用 count 来声明变量,而只有你在知道变量值需要被修改的情况下使用 set 。
模板字符串
模板字符串:使用反引号,插入值:${}
const Box = document.querySelector('#box') let name = 'ysg' let id = 16 let htmlstr = ` <ul> <li> <p id=${id}>${name}</p> </li> </ul> ` Box.innerHTML = htmlstr
函数之默认值
function add(a=10,b=20){ return a + b } console.log(add())
剩余参数
剩余参数:...参数名,解决了 arguments 的问题
function add(a,...keys){ let res = Object.create(null); for(let i=0; i<keys.length; i++){ res[keys[i]] = a[keys[i]] } return res # {name: "ysg", age: "16", city: "新乡"} } let dit = { 'name':'ysg', 'age':'16', 'city':'新乡' } console.log(add(dit,'name','age','city'))
扩展运算符:将一个数组分割,并将各个项作为分离的参数传递给函数
const arr = [12,485,85,156,54,1,6,]
console.log(Math.max(...arr))
箭头函数
箭头函数:使用 => 来定义,相当于 function(){} 等于 ()=>{}
// 无参数 let fun = () => "Hello world" + ' 123' console.log(fun()) let fun = () =>({'name':'ysg','age':'16'}) console.log(fun()) // 一个参数 let fun = val => val console.log(fun(10)) // 两个参数 let add = (a,b) => { return a + b } console.log(add(10,20)) let add = (a,b) => a + b console.log(add(10,20)) // 闭包函数 let fn = (()=>{ return ()=>{ console.log('hello world') } })(); fn();
箭头函数没有 this 指向,箭头函数内部 this 值只能通过查找作用域链接来确定
let PageHandle = { id:123, init:function(){ // 箭头函数没有 this 指向,箭头函数内部 this 值只能通过查找作用域链接来确定 document.addEventListener('click',(event)=>{ this.dcSomeThings(event,type) },false) }, dcSomeThings:function(type){ console.log(`事件类型:${this},当前id:${this.id}`); } } PageHandle.init();
注意:
使用箭头函数注意事项:
1、函数内部没有 arguments
2、不能使用 new 关键字实例化对象
解构赋值
解构赋值是对赋值运算符的一种扩展,它针对数组和对象进行操作;优点:代码书写更简洁易读。
let dit = { 'name':'ysg', 'age':'17' } let {name,age} = dit console.log(name,age) // ysg 17 let list = [1,2,3]; let [a,b,c] = list console.log(a,b,c) // 1 2 3
对象的扩展功能
ES6 允许直接写入变量和函数,作为对象的属性和方法
const name = 'ysg',age = 20 const person = {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; } } cart.set(7); console.log(cart.get());
对象的方法
is() 等价于 === ,比较两个字是否严格相等
console.log(NaN === NaN) // false console.log(Object.is(NaN,NaN)) // true
assign() 用户对象的合并
let newObj = Object.assign({c:3},{a:1},{b:2}) console.log(newObj) # {c: 3, a: 1, b: 2}
Synbol 类型
原始数据类型,它表示独一无二的值,最大的用途:用来定义对象的私有变量
独一无二意味着内存地址不同
// 定义 const name = Symbol('name') const name2 = Symbol('name') console.log(Object.is(name,name2)) // false // 取值 let s1 = Symbol('ysg') console.log(s1) // Symbol(ysg) let obj = { [s1] : '小马哥' } console.log(obj) // {Symbol(ysg): "小马哥"} // 方法一: console.log(obj[s1]) // 小马哥 // 方法二: let s = Object.getOwnPropertySymbols(obj) console.log(s[0]) // 方法三:反射 let m = Reflect.ownKeys(obj); console.log(m)
Set 集合
是一组无重复的有序列表
// 新建集合 let set = new Set() console.log(set) // Set(0) {} // 添加数据 set.add(1) set.add(2) set.add(2) console.log(set) // {1, 2} // 校验数据 console.log(set.has(2)) // true // 查看长度 console.log(set.size) // 2 // 删除数据 set.delete(2); console.log(set) // Set(1) {1} // 将 set 转为数组 let set2 = new Set([1,2,4,5,6]) let lsit = [...set2] console.log(lsit) // [1, 2, 4, 5, 6]
注意:Set 中对象的引用无法被释放,一般是 WeakSet() 来引用
weakSet
1、不能传入非对象类型的参数
2、不可迭代
3、没有 forEach()
4、没有 size 属性
Map 类型
是一组键值对的有序列表,键和值可以是任意类型
let map2 = new Map([ ['张三','zhangsan'], ['李四','lisi'] ]); console.log(map2); let map = new Map() map.set('name','ysg') map.set('age','16') console.log(map) console.log(map.get('name')) console.log(map.has('name')) console.log(map.size) map.delete('name') console.log(map) map.clear() console.log(map)
数据的扩展
from() 将维数组转为真正的数组
<div id = 'box'> <li>1</li> <li>2</li> <li>3</li> <li>4</li> </div> # 简单实例 function add(){ let arr = Array.from(arguments) console.log(arr); } add(1,2,3) let li = document.querySelectorAll('li') // from let list = Array.from(li) console.log(list) // 扩展运算符 let lis = [...li] console.log(lis) // from 还可以传递第二个参数,用来对每个元素进行处理 let list2 = Array.from(li,li=>li.textContent) console.log(list2)
of() 将任意一组数值,转换为数组
of_list = Array.of('1','2','3') console.log(of_list)
copyWithin() 数组内部将指定位置的元素复制到其它的位置,返回当前数组
list = [1,2,3,4,5,6,7,8].copyWithin(0,3)
console.log(list)
find() 查找元素,返回第一个符合条件的元素
findindex() 查找索引,返回第一个符合条件的元素下标
let num = [1,2,3,4,5,6,7,8].find(n => n > 6) console.log(num) // 7 let num2 = [1,2,3,4,5,6,7,8].findIndex(n => n > 6) console.log(num2) // 6
keys()、values()、entries() 遍历器,可以使用 for ... of 循环进行遍历
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) // 索引,值:(2) [0, "a"] (2) [1, "b"] }
includes() 返回一个布尔值,表示某个数组是否包含指定的值
console.log([1,2,3].includes(3)) // true
console.log([1,2,3].includes(4)) // false
迭代器
1、迭代器是一个接口,能快捷的方位数据,通过 Symbol.iterator 来创建迭代器,通过迭代器的 next() 获取值
2、迭代器是用于遍历数据结构的指针(类似于数据库中的游标)
const items = ['ysg','ysging','czx'] const ite = items[Symbol.iterator](); console.log(ite.next()); // {value: "ysg", done: false} done 如果为 false,表示遍历继续,为 true 表示遍历完成 console.log(ite.next()); console.log(ite.next()); console.log(ite.next());
生成器
generator 函数,可以通过 yield 关键字,将函数挂起,为了改变执行流提供了可能,同时为异步编程提供了方案
语法:function* add() { yield x}
function* add() { console.log('one') let x = yield '2'; console.log('one:' + x) let y = yield '3'; console.log('two:' + y) return x + y; } const fn = add(); // one console.log(fn.next()); // {value: "2", done: false} console.log(fn.next(30)); // {value: "3", done: false} console.log(fn.next(20)); // {value: 50, done: true}
使用场景,为不具备 Interator 接口的对象提供了遍历操作。
Promise 承诺
相当于一个容器,保存着未来才会结束的事件(异步操作)的一个结果
各种异步操作都可以用同样的方法进行处理 axios
特点:
1.对象的状态不受外部影响 处理异步操作,三个状态 Pending(进行) Resolved(成功) Rejected(失败)
2.一旦状态改变,就不会在变,任何时候都可以得到这个结果。
function timeOut(ms) { return new Promise((resolved,Rejected)=>{ setTimeout(() => { resolved('hello promise success!!!') },ms); }) } timeOut(2000).then((val)=>{ console.log(val) // hello promise success!!! })
Promise对象的其它用法
resolve() reject() all() race() done() finally()
resolve() 将任意类型的对象转为 promise 对象
reject() 与 resolve() 效果一样
let p = new Promise(resolve=>resolve('foo')); p.then((data)=> console.log(data) // foo ) console.log(p) // Promise {<resolved>: "foo"}
all() 所有异步 Promise 方法执行成功,才执行后续内容
应用:一些游戏类的素材比较多,等待图片、flash、静态文件 都加载完成,才进行页面的初始化
let p1 = new Promise((resolve,reject)=>{}); let p2 = new Promise((resolve,reject)=>{}); let p3 = new Promise((resolve,reject)=>{}); let p = Promise.all([p1,p2,p3]) p4.then(()=>{ // 三个都成功,则成功 }).catch(err=>{ // 如果一个失败,则失败 })
race() 用于设置超时时间,并在超时后执行相应的操作
请求图片资源
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('图片请求超时') },1000) }) } Promise.race([requestImg('https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1594089011992&di=9847cc1d804fbccdf77e67d9bcdc61aa&imgtype=0&src=http%3A%2F%2Fi4.17173.itc.cn%2F2010%2Fnews%2F2010%2F03%2F01%2Ft0301syu01s.jpg'),timeout()]).then(res=>{ console.log(res) }).catch(err=>{ console.log(err); })
done() finally() 无论 Promise 成功与否,都执行其中的内容,比较少用
async的用法
作用:使得异步操作更加方便
基本操作:async 它会返回一个 Promise 对象,then catch
async 是 Generator 的一个语法糖
// 成功的操作 async function fun() { let s = await 'hello world' let data = await s.split('') return data; } fun().then(v=>{console.log(v)}).catch(e=>console.log(e)) // 失败的操作 async function fun2() { try{ throw new Error('出错了') }catch(errer){ } return await Promise.resolve('hello') } fun2().then(v=>{console.log(v)}).catch(e=>console.log(e))
class类的用法
class Person { // constructor 实例化的时候会立即被调用 constructor(name,age){ this.name = name this.age = age } // 添加方法 方法一 // getName(){ // return this.name // } // getAge(){ // return this.age // } } // 添加方法 方法二 // 通过 Object.assign() 一次性向类中添加多个方法(用的不多) Object.assign(Person.prototype,{ getName(){ return this.name }, getAge(){ return this.name } }) let p = new Person('ysg',16) // console.log(p) // Person {name: "ysg", age: 16} console.log(p.getName()) // ysg
类的继承
class Animal{ constructor(name,age){ this.name = name this.age = age } getName(){ return this.name } getAge(){ return this.age } } class Dog extends Animal{ constructor(name,age,color){ super(name,age); this.color = color; } // 新建类 getColor(){ return this.color } // 重写类 getName(){ return this.name + this.age + this.color } } let d = new Dog('小左',3, 'red') console.log(d.getName()) console.log(d.getColor())
ES6的模块化实现
es6主要有两个命令构成:export 和 import
exprot:用于规定模块的对外接口
import:用于输入其它模块提供的功能
一个模块就是一个独立的文件
模块文件:index.js
// 方法一 export name = 'ysg' export function fun() { // body... return 'my name is ' + name } // 方法二 age = '16' function fun2(){ return '年龄: ' + age } export{ age,fun2 } // 方法三,使用别名 class Person(){ constructor(){ } getAge(){ console.log(age) } getName(){ console.log(name) } } export default Person
调用文件:model.html
import {name} from './index.js' console.log(name) // 使用别名调用 import Person from './index.js' const p = new Person(); console.log(Person(p.getName))