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)
}
posted @ 2020-05-16 00:36  风灵灵  阅读(209)  评论(0编辑  收藏  举报