es6知识点
ES6的基础语法
- var的问题
- 可以重复声明,没有报错和警告
- 无法限制修改
- 没有块级作用域,
- let/const
es6中新增的用来创建变量和常量的,基于const创建变量,变量存储的值不能被修改(常量)
let 和var的区别
- let不存在变量提升(当前作用域中,不能在let声明前使用变量)
- 同一个作用域中,let不允许重复声明
- let解决了typeof的一个暂时性死区的问题
- 全局作用域中,使用let声明的变量并没有给window加上对应的属性
- let会存在块作用域(除对象以外的大括号都可以被看作私有作用域)
块级作用域举例
- 原来用 var 的方式,结果弹出的都是 3
- 或者将变量 封装到函数里,限制作用域,但比较麻烦
- 用 let 最简单,直接 var 改 let,解决作用域问题
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script>
window.onload= function () {
/*
var aBtn = document.getElementsByTagName('input')
for (var i=0; i < aBtn.length; i++) {
aBtn[i].onclick = function () {
alert(i)
}
}*/
var aBtn = document.getElementsByTagName('input')
for (let i = 0; i < aBtn.length; i++) {
aBtn[i].onclick = function () {
alert(i)
}
}
/*
var aBtn = document.getElementsByTagName('input')
for (var i = 0; i < aBtn.length; i++) {
// 封装到函数里,限制作用域
(function (i) {
aBtn[i].onclick = function () {
alert(i)
}
})(i)
}*/
}
</script>
</head>
<body>
<input type="button" value="按钮1">
<input type="button" value="按钮2">
<input type="button" value="按钮3">
</body>
</html>
箭头函数及this问题
ES6中新增了创建函数的方式:“箭头函数”
真实项目中是箭头函数和function这种普通函数混合使用
- 箭头函数简化了创建函数的代码
- 如果只有一个参数,() 可以省
- 如果只有一个return,{}可以省
// 普通函数
function name() {
}
// 箭头函数,去掉 function, 加上 =>
() => {
}
//箭头函数的创建都是函数表达式方式(变量=函数),这种模式下,不存在变量提升,也就是函数只能在创建完成后被执行
const fn=([形参])=>{
//函数体 (return)
};
fn([实参]);
//形参只有一个,小括号可以不加
const fn=n=>{};
//函数体中只有一句话,并且是return xxx的,可以省略大括号和return等
function fn(n){
return function(m){
return m+(++n);
}
}
简化为箭头函数
const fn=n=>m=>m+(++n);
箭头函数中没有arguments,但是可以基于剩余运算符获取实参集合,而且ES6中是支持给形参设置默认值的
let obj = {};
let fn = (context = window,...arg) =>{
//...arg:剩余运算符(把除第一项外的,其他传递的实参信息都存储到arg这个数组集合中)
console.log(arg);
};
fn(obj,10,20,30);//context:obj arg:[10,20,30]
fn();//context:window arg:[]
箭头函数中没有自己的this,它里面用到的this,都是自己所处上下文中的this(真实项目中,this要慎用)
window.name = 'window';
let obj = {
name:'OBJ'
};
let fn = n =>{
console.log(this.name);
};
//FN所处的执行上下文中的this是window
fn(10);//this:window
fn.call(obj,10);//this:window 不是我们预期的OBJ
document.body.onclick = fn;//this:window 不是我们预期的body
真实项目中的一个应用
let obj = {
name:'obj',
fn:function(){
//原本期望的需求是:1s后把obj中的name改为"珠峰"
setTimeout(()=>{
console.log(this);//obj
this.name='珠峰';
},1000);
}
}
解构赋值
让左边出现和右侧值相同的结构,以此快速获取到我们需要的内容
真实项目中最常用的就是对数组的解构
- 数组的解构赋值
let ary = [10,20,30,40,50];
let [n,m,...x] = ary;
//...x拓展运算符:把剩下的内容存储到x中(x是个数组),但是它只能出现在最后
console.log(n,m,x)//10,20,[30,40,50]
let [n,,m]//10,30
let [n,,m,,,x=0] = ary;//如果没有这一项,我们可以基于等号赋值默认值
console.log(n,m,x);//10,30,0
let ary = [10,[20,30,[40,50]]];
let [n,[,,[,m]]] = ary;//10,50
- 对象的解构赋值
let obj = {
name:'王会峰,
age17,
sex:boy,
friends:['1','2','3']
}
let{
name,
sex,
age
} = obj;
console.log(name,sex,age);//王会峰,boy,17
//解构赋值
let [n,...m] = [12,23,34];
//n:12
//m:[23,34]
//传递实参
let ary=[12,23,13,24,10,25];
let min=Math.min(...ary);
//数组克隆(浅克隆)
let cloneAry=[...ary];
//对象克隆(浅克隆)
let obj={name:'xx',age:16};
let cloneobj={...obj,sex:'girl',age:17};
//接收实参
let fn=(n,...arg)=>{
//n:10
//arg:[20,30]
};
fn(10,20,30)
函数-参数
"..."的作用
- 拓展运算符(多用在解构赋值中)
- 展开运算符 (多用在传递实参中)
- 剩余运算符 (多用在接收实参中)
function show(a, b, ...args) {
console.log(a)
console.log(b)
console.log(args)
}
console.log(show(1, 2, 3, 4, 5))
let arr1 = [1, 2, 3]
let arr2 = [4, 5, 6]
let arr3 = [...arr1, ...arr2]
console.log(arr3)
function show2(a, b=5, c=8) {
console.log(a, b, c)
}
show2(88, 12)
class 创建类
- 旧版本
- 类和构造函数一样
- 属性和方法分开写的
// 老版本
function User(name, pass) {
this.name = name
this.pass = pass
}
User.prototype.showName = function () {
console.log(this.name)
}
User.prototype.showPass = function () {
console.log(this.pass)
}
var u1 = new User('able', '1233')
u1.showName()
u1.showPass()
// 老版本继承
function VipUser(name, pass, level) {
User.call(this, name, pass)
this.level = level
}
VipUser.prototype = new User()
VipUser.prototype.constructor = VipUser
VipUser.prototype.showLevel = function () {
console.log(this.level)
}
var v1 = new VipUser('blue', '1234', 3)
v1.showName()
v1.showLevel()
- 新版本
- 有了 class 关键字、构造器
- class 里面直接加方法
- 继承,super 超类==父类
class User {
constructor(name, pass) {
this.name = name
this.pass = pass
}
showName() {
console.log(this.name)
}
showPass() {
console.log(this.pass)
}
}
var u1 = new User('able2', '111')
u1.showName()
u1.showPass()
// 新版本继承
class VipUser extends User {
constructor(name, pass, level) {
super(name, pass)
this.level = level
}
showLevel(){
console.log(this.level)
}
}
v1 = new VipUser('blue', '123', 3)
v1.showLevel()
//ES6中类的创建
class Fn{
//等价于之前的构造函数体
constructor(){
this.X=100;
}
//直接写的方法就是加在原型上的
getX(){
console.log(this.x);
}
//前面设置static的:把当前fn当做普通对象设置的键值对
static queryX(){}
}
//也可以在外面单独这样写
let f = new Fn(10,20);
f.getX();
Fn.queryX();
ES6中的模板字符串
let year = '2020',
month = '05',
day = '15';
let res = `你好,小伙伴!今天是${year}年${month}月${day}日.`
Promise --消除异步操作
异步:操作之间没啥关系,同时进行多个操作(代码更复杂)
同步:同时只能做一件事(代码简单)
- Promise 对象
- 用同步的方式来书写异步代码
- Promise 让异步操作写起来,像在写同步操作的流程,不必一层层地嵌套回调函数
- 改善了可读性,对于多层嵌套的回调函数很方便
- 充当异步操作与回调函数之间的中介,使得异步操作具备同步操作的接口
- Promise 也是一个构造函数
- 接受一个回调函数f1作为参数,f1里面是异步操作的代码
- 返回的p1就是一个 Promise 实例
- 所有异步任务都返回一个 Promise 实例
- Promise 实例有一个then方法,用来指定下一步的回调函数
function f1(resolve, reject) {
// 异步代码...
}
var p1 = new Promise(f1);
p1.then(f2); // f1的异步操作执行完成,就会执行f2。
- Promise 使得异步流程可以写成同步流程
// 传统写法
step1(function (value1) {
step2(value1, function(value2) {
step3(value2, function(value3) {
step4(value3, function(value4) {
// ...
});
});
});
});
// Promise 的写法
(new Promise(step1))
.then(step2)
.then(step3)
.then(step4);
- Promise.all(promiseArray)方法
- 将多个Promise对象实例包装,生成并返回一个新的Promise实例
- promise数组中所有的promise实例都变为resolve的时候,该方法才会返回
- 并将所有结果传递results数组中
- promise数组中任何一个promise为reject的话,则整个Promise.all调用会立即终止,并返回一个reject的新的promise对象
var p1 = Promise.resolve(1),
p2 = Promise.resolve(2),
p3 = Promise.resolve(3);
Promise.all([p1, p2, p3]).then(function (results) {
console.log(results); // [1, 2, 3]
});
Promise.race的用法
Promise.race([
$.ajax({url:'http://...'});
$.ajax({url:'http://...'});
$.ajax({url:'http://...'});
])
JSON
json的标准写法:
1.只能用双引号
2.所有名字都必须用引号包起来
- json对象
- JSON.stringify(obj):接受一个 JavaScript 对象并将其转换为一个 JSON 字符串。
- JSON.parse(string):接受一个 JSON 字符串并将其转换成一个 JavaScript 对象。
var json = {a: 12, b: 5}
var str = 'hi,' + JSON.stringify(json)
var url = 'http://www.xx.com/' + encodeURIComponent(JSON.stringify(json))
console.log(str)
console.log(url)
var str = '{"a": 12, "b": 4, "c": "abc"}'
var json = JSON.parse(str)
console.log(json)
hi,{"a":12,"b":5}
http://www.xx.com/%7B%22a%22%3A12%2C%22b%22%3A5%7D
{ a: 12, b: 4, c: 'abc' }
-
json简写
- 名字一样(两个一样简写为一个)
- 方法
//show:function(){...} //show(){...} let json={ a:12, show(){ alert(this.a); } }; json.show();
generator生成器
- generator 生成器函数
- 普通函数,一路到底
- generator函数,中间可以停,到哪停呢,用 yield 配合,交出执行权
- yield 有 放弃、退让、退位的意思
- 需要调用next()方法启动执行,需要遇到 yield 停, 踹一脚走一步
- generator函数前面加一个 * 两边可以有空格,或靠近函数或function
- 背后实际生成多个小函数,实现走走停停
function show() {
console.log('a')
console.log('b')
}
show() // 普通函数
function *show2() {
console.log('1')
yield
console.log('2')
}
let genObj = show2()
genObj.next() // 1
genObj.next() // 2
genObj.next() // 最后了,没有结果
yield
- 既可传参,又可以返回
- 第一个next()传参无效,只用来启动
- 如果函数前漏掉 *
- 就是普通函数
- 如果有yield会报错, ReferenceError: yield is not defined
- yield 只能在Generator函数内部使用
function * show() {
console.log('1')
var a = yield
console.log('2')
console.log(a)
}
// yield 传参
var gen = show()
gen.next() // 1
gen.next() // 2 和 undefined 因为没有传参,yield没有返回值
var gen = show()
gen.next(10) // 1 第一次执行到yield,但没有执行赋值
gen.next(20) // 2 和 20
function* show2() {
console.log('1')
yield 10
console.log('2')
}
// yield 返回
var gen = show2()
var res1 = gen.next()
console.log(res1) // { value: 10, done: false }
var res2 = gen.next()
console.log(res2)
// { value: undefined, done: true } 最后的value需要return返回
generator-实例
- Promise 适合一次读一组
- generator 适合逻辑性的
// 带逻辑-generator
runner(function * () {
let userData = yield $.ajax({url: 'getUserData'})
if (userData.type == 'VIP') {
let items = yield $.ajax({url: 'getVIPItems'})
} else {
let items = yield $.ajax({url: 'getItems'})
}
})
// yield 实例,用同步方式写异步
server.use(function * () {
let data = yield db.query(`select * from user_table`)
this.body = data
})
数组方法
- map 映射
let arr = [12, 5, 8]
let result = arr.map(function (item) {
return item*2
})
let result2 = arr.map(item=>item*2) // 简写
console.log(result)
console.log(result2)
let score = [18, 86, 88, 24]
let result3 = score.map(item => item >= 60 ? '及格' : '不及格')
console.log(result3)
// 结果
[ 24, 10, 16 ]
[ 24, 10, 16 ]
[ '不及格', '及格', '及格', '不及格' ]
- reduce 汇总一堆出来一个
- 用于比如,算个总数,算个平均
var arr = [1, 3, 5, 7]
var result = arr.reduce(function (tmp, item, index) {
//tmp 上次结果,item当前数,index次数1开始
console.log(tmp, item, index)
return tmp + item
})
console.log(result)
var arr = [1, 3, 5, 7]
var result = arr.reduce(function (tmp, item, index) {
if (index != arr.length - 1) { // 不是最后一次
return tmp + item
} else {
return (tmp + item)/arr.length
}
})
console.log(result) // 平均值
- filter 过滤器 保留为true的
var arr = [12, 4, 8, 9]
var result = arr.filter(item => (item % 3 === 0) ? true : false)
console.log(result)
var result = arr.filter(item => item % 3 === 0)
console.log(result)
var arr = [
{ title: '苹果', price: 10 },
{ title: '西瓜', price: 20 },
]
var result = arr.filter(json => json.price >= 20)
console.log(result)
- forEach 循环迭代
var arr = [12, 4, 8, 9]
var result = arr.forEach(item => console.log(item))
var result = arr.forEach((item, index)=>console.log(item, index))
字符串
- startsWith/endsWitn
var url = 'http://qq.com'
console.log(url.startsWith('http'))
console.log(url.endsWith('com'))
// 都是 true
- 字符串模板:
${a}xxx${b}
- 使用反引号,$
- 可以折行
let a = 12
let str1 = `asdf${a}`
console.log(str1)
let title = '标题'
let content = '内容'
let str = `<div>
<h1>${title}</h1>
<p>${content}</p>
`
console.log(str)
<div>
<h1>标题</h1>
<p>内容</p>
数组
- arr.includes() 数组是否包含某个东西
- 数组的 arr.keys(), arr,entries()
- for...of//循环的是下标(key)
- for...in//循环的是值(value),不能用于json
- entries=》将所有的key,value拿出来
let arr = ['a', 'b', 'c']
console.log(arr.includes(1))
for (let i in arr) {
console.log(i) // 循环的时下标 key
}
for (let i of arr) {
console.log(i) // 循环的是值 value
}
for (let i of arr.keys()) {
console.log('>'+i)
}
for (let [key, value] of arr.entries()) {
console.log('>' + key + value)
}
let json = { a: 12, b: 5, c: 7 }
for (let i in json) {
console.log(i)
}
- 字符串
- padStart()/padEnd() 指定宽度,不够就补空格或指定字符
console.log('=' + 'abcd'.padStart(6, '0') + '=')
console.log('=' + 'abcd'.padEnd(6, '0') + '=')
=00abcd=
=abcd00=
- 容忍度
- [1, 2, 3,] 老版数组最后不能有逗号,新的可以有
- 函数参数最后多的逗号也可以
- async await
- 和 generator yield 类似
- generator 不可以写成箭头函数, async 可以
async function show() {
console.log(1)
await
console.log(2)
}