ES6学习笔记

118 阅读10分钟

ES6(尚硅谷)

[1.let声明变量]

  • 变量不能重复声明
  • 块级作用域有效,只在代码块中起作用
  • 不存在变量提升(要先声明再使用)
  • 不影响作用域链
//1.变量不能重复声明
let star='z';
let star='x';//报错

[2.const声明常量]

  1. 一定要有初始值
  2. 一般常量使用大写
  3. 常量的值不能修改
  4. 块级作用域
  5. 对于数组和对象的元素修改,不算做对常量的修改,不会报错(指向的地址没有发生改变)
const TEAM=['A','B'];
TEAM.push('C');//给数组添加一个元素C

[3.变量的解构赋值]

ES6允许按照一定模式从数组和对象中提取值,对变量进行赋值,被称为解构赋值

  • 数组的解构

将数组的单元值快速批量赋值给一系列变量的简洁语法

const F4 = ['小沈阳''刘能','赵四','宋小宝']
let [xiao,liu,zhao,song] = F4; //中括号
console.log(xiao)
console.log(liu)
console.log(zhao)
console.log(song)
  • 对象的解构

将对象属性和方法快速批量赋值给一系列变量的简洁语法

const zhao = {
    name : '赵本山'age: '不详',
    xiaopin: function(){
        console.log("我可以演小品")
    }
}
let {name,age,xiaopin} = zhao;//花括号
console.log(name);
console.log(age);
console.log(xiaopin);

[4.模板字符串]

  1. 声明
let str = `我也是一个字符串`
console.log(str,typeof str);
  1. 特点
  • 内容中可以直接出现换行符
let str = `<ul>
			<li>RHF</li>
			<li>RHF</li>
		   </ul>`;
  1. 变量拼接

${lovest}

let lovest = 'RHF';
let out = `${lovest}是最帅的`;
console.log(out)  //RHF是最帅的

[5.对象的简化写法]

ES6允许在大括号里面,直接写入变量和函数,作为对象的属性和方法

let name = 'aaa';
let change = function(){
    console.log('aaa');
}

const school = {
    name,
    change,
    improve(){
        consolg.log('bbb');
    }
}

[6.箭头函数]

属于表达式函数,不存在变量提升

  1. this是静态的,this始终指向函数声明时所在作用域下的this的值(箭头函数不会创建自己的this,只会从自己的作用域链的上一层沿用this)
function A(){
    console.log(this.name)
}

let B = () => {
    console.log(this.name);
}

window.name = '尚硅谷';
const school = {
    name: 'ATGUIGU'
}

//直接调用
A()   //尚硅谷
B()  //尚硅谷

//call
A.call(school); //ATGUIGU****
B.cal(school);  //尚硅谷****

  1. 不能作为构造实例化对象(对象的方法——>外层作用域的this)
let A(name,age) => {
    this.name=name;
    this.age=age;
}
let me = new A('xiao',123);
console.me //error
  1. 不能使用arguments变量(可使用剩余参数)
let fn = () => {
    console.log(arguments);
}
fn(1,2,3)  //error
  1. 箭头函数可以直接返回一个对象(加括号的函数体返回对象字面量的表达式)
const fn = (unname)=>
({
    name:unname;//对象花括号易混函数体花括号,要加个小括号
})
  1. 简写
  • 省略小括号,当形参有且只有一个的时候
  • 省略花括号,当代码体只有一条语句的时候,此时return也必须省略
  • 箭头函数适合与this无关的回调(定时器,数组方法的回调)
  • 箭头函数不适合与this有关的回调(DOM事件回调[事件回调函数使用箭头函数时,this为全局的window],对象的方法)

[7.函数默认参数值]

  • ES6允许给函数参数赋初始值
  • 传了新的参数就用传的参数,没有传参就用默认值
  • 可以给形参赋初始值,一般位置要靠后
  • 与解构赋值结合
function A({host='127.0.0.1',username,password,port}){
    console.log(host+username+password+port)
}
A({
    username:'ran',
    password:'123456',
    port:3306
})

[8.rest参数]

用于获取函数的实参,用来代替arguments

  • rest参数必须放到参数(函数使用的形参)最后

[9.扩展运算符...]

能将数组转换为逗号分隔的参数序列

  1. 数组的合并
const A = ['aa','bb'];
const B = ['cc','dd'];
const C = [...A,...B];
console.log(C)   //[aa,bb,cc,dd]
  1. 数组的克隆
const A = ['a','b','c'];
const B = [...A];
console.log(B)   //[a,b,c]
  1. 将伪数组转化为真正的数组
const A = documents.querySelectorAll('div');
const B = [...A];
console.log(B) // [div,div,div]

[10.Symbol]

ES6引入了一种新的原始数据类型Symbol,表示独一无二的值。它是Javascript语言的第七种数据类型,是一种类似于字符串的数据类型。

特点

  • Symbol的值是唯一的,用于解决命名冲突的问题
  • Symbol不能与其他的数据类型进行运算
  • Symbol定义的对象属性不能使用for...in...循环遍历,但是可以使用Reflect.ownKeys来获取对象的所有键名
  1. 创建
let s = Symbol('aa');
let s2= Symbol('aa');
console.log(s===s2)   //false

let s3 = Symbol.for('bb');
let s4 = Symbol.for('bb');
comsole.log(s3===s4) ///true
  1. Symbol的内置值
class Person {
    static [Symbol.hasInstance](param){
        console.log(param);
        console.log("我被用来检测了");
        return false;
    }
}
let o = {};
console.log(o instanceof Person); //我被用来检测了,false

应用

  • 给对象添加方法(1)
let game = {
    name : 'ran'
}
let methods = {
    up:Symbol()
    down:Symbol()
}
game[methods.up]=function(){
    console.log('aaa');
}
game[methods.down]=function(){
    console.log('bbb');
}
console.log(game)    // name: 'ran',Symbol(),Symbol()
  • 给对象添加方法(2)
//不用查找对象原来有无此方法名
let youxi = {
    name: '狼人杀',
    [Symbol('say')]:function(){
        console.log('阿萨德')
    }
}
console.log(youxi)    // name:'狼人杀',Symbol(say)

[11.迭代器]

  • 迭代器(lterator)是一种接口,为各种不同的数据结构提供统一的访问机制。
  • 任何数据结构只要部署lterator接口,就可以使用for...of...完成遍历操作。

具备iterator接口的数据类型

  • Array
  • Argunments
  • Set
  • Map
  • String
  • TypedArray
  • NodeList

这个接口就是对象里面的一个属性,属性的名字叫Symbol.iterator,也可以自己对结构进行布置iterator接口。

工作原理

  1. 先创建一个指针对象,指向当前数据结构的起始位置
  2. 第一次调用next()方法,指针自动指向数据结构的第一个成员
  3. 接下来不断调用next()方法,指针一直往后移动,直到指向最后一个成员
  4. 每次调用next()方法就会返回一个包含valuedone属性(是否完成)的对象

迭代器可以自定义遍历数据

for...in...与for...of...

for(let i in data){
i是键名
}
for(let i of data){
i是键值
}

数组常用的遍历方法

  • forEach:找到目标还会继续循环,并且不受returnbreak的影响
  • some:找到目标后,可以通过return结束循环
const arr=[]
arr.some((item,index)=>{
  if(item=='zzl'){
    console.log(item)
    return true
  }
})
  • every:只要每一项都满足every里面的判断条件,则最终返回ture
const arr=[
  {id:1,state:true},
  {id:2,state:true}
]
//判断数组中的所有state是否都为true
const result=arr.every(item=>item.state)
  • filter:把满足条件的数据重新过滤到新数组中
const data=arr.filter(item=>item.state)
  • reduce:第一次循环累加的结果默认等于初始值,以后循环累加的结果等于上一次累加的结果加上循环项里的数据。
arr.filter(item=>item.state).reduce(累加的结果,当前循环项)=>{ },初始值)
const arr=[{id:1,state:true,price:10}]
let sum=0
arr.filter(item=> item.state).reduce((sum,item)=>{
    return sum+= item.price
    //return给下一次累加使用
},0)

[12.生成器]

生成器是一个特殊的函数,是异步编程新的解决方案。

  • 函数名和function中间有一个*
  • yield是函数代码的分隔符
  • 需要用next()方法调用,依次执行以yield分割的一段,并且返回yield后面的值
  • next()中传入的值将作为yield的返回结果
function * fun(){
    console.log('111');
    yield '返回值'
    console.log('222');
}
let a=fun();


//输出
//console.log(a);//输出一个迭代器对象(有next方法)
console.log(a.next());//输出111{value:'返回值',done:'false'}
console.log(a.next());//输出222{value:'undefined',done:'ture'}


//遍历
for(let v of fun()){
    console.log(v);
}
//111
//返回值
//222

生成器函数的参数传递

function * fun(arg){
    console.log(arg);//输出aaa
    let one=yield 111;
    console.log(one);//输出bbb
    let two=yield 222;
    console.log(two);//输出ccc
    let three=yield 333;
    console.log(three);//输出ddd
}
let a=fun('aaa');
console.log(a.next());//第一次调用next
//next方法可以传入实参
//第二次调用next的实参将作为第一个yield的整体返回结果
console.log(a.next('bbb'))//输出{value: 222, done: false}
console.log(a.next('ccc'))
console.log(a.next('ddd'))

用生成器函数的方式解决回调地狱的问题

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();

模拟异步获取数据

function one(){
    setTimeout(()=>{
        let data='用户数据';
        iterator.next(data)//调用并传参
    },1000)
}
function two(){
    setTimeout(()=>{
        let data='订单数据';
        iterator.next(data)
    },2000)
}
function three(){
    setTimeout(()=>{
        let data='商品数据';
        iterator.next(data)
    },3000)
}

function * gen(){
    let users=yield one();
    console.log(users)
    let orders=yield two();
    console.log(orders)
    let goods=yield three();
    console.log(goods)
}

let iterator = gen();
iterator.next();

[13.Promise]

异步编程新的解决方法,语法上Promise是一个构造函数,用来封装异步操作并可以获取其成功或者失败的结果。

function fun(){
    return new Promise((resolve,reject)=>{
        //如果成功就调用resolve
        let data='数据库中的数据';
        resolve(data); //promise状态变为成功
        //如果失败就调用reject
        let err='数据库读取失败';
        reject(err);//promise状态变为失败
    })
}
var promise = fun()
promise.then(//调用then方法
    function(success){//promise状态变为成功后then会调用第一个回调函数
        console.log(success);
    },function(err){//promise状态变为失败后then会调用第二个回调函数
        console.log(err);
    }
)

Promise.then()方法

  • then()函数返回的实际也是一个Promise对象
  • 当回调后,返回的是非Promise类型的属性时,状态为fulfilled,then()函数的返回值为对象的成功值,如reutnr 123,返回的Promise对象值为123,如果没有返回值,是undefined
  • 当回调后,返回的是Promise类型的对象时,then()函数的返回值为这个Promise对象的状态值
  • 当回调后,如果抛出的异常,则then()函数的返回值状态也是rejected

Promise.catch()方法

  • catch()函数只有一个回调函数,意味着如果Promise对象状态为失败就会调用catch()方法并且调用回调函数
  • 相当于一个语法糖,直接在出错的时候使用reason,只有Promise.then也能实现
<script>
    const p = new Promise((resolve, reject) => {
        setTimeout(()=>{
            reject('出错啦')
        },1000)
    })

    p.catch(reason => {
        console.log(reason)
    })
</script>

[14.集合]

Set

ES6提供了新的数据结构set(集合)。它类似于数组,但成员的值都是唯一的,集合实现了iterator接口,所以可以使用扩展运算符 for…of…进行遍历,集合的属性和方法:

  • size返回集合的元素个数
  • add增加一个新元素,返回当前集合
  • delete删除元素,返回boolean值
  • has检测集合中是否包含某个元素,返回boolean值
<script>
    let s = new Set();
    let s2 = new Set(['A','B','C','D'])

    //元素个数
    console.log(s2.size);

    //添加新的元素
    s2.add('E');

    //删除元素
    s2.delete('A')

    //检测
    console.log(s2.has('C'));

    //清空
    s2.clear()

    console.log(s2);
</script>

应用

let arr=[1,2,3,4,3,2,1];
//数组去重
let result=[...new Set(arr)];//[1,2,3,4]


//交集
let arr2=[1,4,5,6,5,6];
let result2=[...new Set(arr)].filter(item=>{
    let s2=new Set(arr2);//[1,4,5,6]
    if(s2.has(item)){
        return true;
    }else{
        return false;
    }
})
console.log(result2);//[1,4];


//并集
let arr3=[...new Set([...arr,...arr2])]
console.log(arr3);//[1,2,3,4,5,6]

//差集,交集的逆运算
let arr2=[1,4,5,6,5,6];
let result2=[...new Set(arr)].filter(item=>{
    let s2=new Set(arr2);//[1,4,5,6]
    if(!s2.has(item)){//item不在s2里面
        return true;
    }else{
        return false;
    }
})
console.log(result2);//[1,4]

Map

ES6提供了Map数据结构。它类似于对象,也是键值对的集合。但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。Map也实现了iterator接口,所以可以使用『扩展运算符』和「for…of…』进行遍历。

  1. size:返回Map元素的个数
  2. set:增加一个新元素,返回当前Map
  3. get:返回键名对象的键值
  4. has:检测Map中是否包含某个元素,返回Boolean值
  5. clear:清空集合,返回undefined

[15.Class]

ES6提供了更接近传统语言的写法,引入了Class(类)这个概念,作为对象的模板。通过class关键字,可以定义类。基本上,ES6的class可以看作只是一个语法糖,它的绝大部分功能,ES5都可以做到,新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。

  • js高级笔记里面更详细,待补充

[16.数值扩展]

  • Number.EPSILON是 JavaScript的最小精度,属性的值接近于 2.22044...E-16
   function equal(a,b){
       if(Math.abs(a-b) < Number.EPSILON){
           return true;
       }else {
           return false;
       }
   }

   console.log(equal(0.1 + 0.2 === 0.3))  //false
   console.log(equal(0.1+0.2,0.3))  //true
  • 二进制和八进制
   let b = 0b1010; //2进制
   let o = 0o777;  //8进制
   let d = 100;    //10进制
   let x = 0xff;   //16进制
   console.log(x)   //255(输出的都是十进制)
 //检测一个数是否为有限数
 console.log(Number.isFinite(100));  //true
 console.log(Number.isFinite(100/0));  //false
 console.log(Number.isFinite(Infinity));  //false

 //检测一个数值是否为NaN
 console.log(Number.isNaN(123))  //false

 //字符串转整数
 console.log(Number.parseInt('5213123love')); //5213123
 console.log(Number.parseFloat('5.123123神器')); //5.123123

 //判断是否为整数
 console.log(Number.isInteger(5));  //true
 console.log(Number.isInteger(2.5)); //false
 
 //将小数部分抹除
 console.log(Math.trunc(3.45345345345)) //3

 //检测一个数到底是正数、负数、还是0
 console.log(Math.sign(100)) //1
 console.log(Math.sign(0))  //0
 console.log(Math.sign(-123)) //-1

[17.对象方法扩展]

<script>
    //1.Object.is 判断两个值是否完全相等
    console.log(Object.is(120,120))  //true
	console.log(Object.is(NaN,NaN))  //false


    //2.Object.assign 对象的合并
    //如果两个对象有重复的属性或方法,后面的会将前面的内容覆盖
    const a = {
        name:'ran',
        age:12
    }
    const b = {
        pass:'i love you'
    }
    console.log(Object.assign(a,b))
    //{name:'ran',age:'12',pass:'i love you'}


    //3.Object.setPrototypeOf 设置原型对象 Object.getPrototypeof
    const school = {
        name:'尚硅谷'
    }
    const cities = {
        xiaoqu:['北京','上海']
    }
    Object.setPrototypeOf(school,cities)
    console.log(Object.getPrototypeOf(school)) 
    //{xiaoqu: Array(2)}
    console.log(school)  //{name: "尚硅谷"}
</script>

[18.模块化]

模块化是指将一个大的程序文件,拆分成许多小的文件,然后将小文件组合起来。

模块功能主要有两个命令构成:export和inport

  • export命令用于规定模块的对外接口
  • inport命令用于输入其他模块提供的功能

暴露export

  1. 统一暴露
let school = '尚硅谷';
function findjob(){
    console.log('找工作吧');
}
export {school,findjob}
  1. 默认暴露
export default {
    school:'ATGUIGU',
    change:function(){
        console.log('我们可以改变你')
    }
}

引入语法import

  1. 通用导入方式
import * as m1 from "./src/js/m1.js"
import * as m2 from "./src/js/m2.js"
import * as m3 from "./src/js/m3.js"
  1. 解构赋值
import {school,teach} from "./src/js/m1.js"
import {school as guigu,findJob} from "./src/js/m2.js"
import {default as m3 } from "./src/js/m3.js"
  1. 简便形式(只针对默认暴露)
import m3 from "./src/js/m3.js"