ES6基础知识总结

一、ES6介绍

1.ES6介绍
ES6是ES2015、ES2016、ES2017他们的统称
官方名字:《ECMAScript 2015 标准》=> ES6
2.包管理机制(npm)
1)初始化项目
npm init -y 初始化项目(不询问项目信息)
2)安装依赖
全局依赖(在电脑的C盘保存依赖的源码)
cnpm install xxx --global
简写:cnpm i xxx -g
局部依赖(在项目的根目录下保存依赖源码信息)
开发依赖
cnpm install xxx --save-dev
简写:cnpm i xxx -D
产品依赖
cnpm install xxx --save
简写:cnpm i xxx -S
3.Bable安装与使用
安装
cnpm install babel-cli -g
cnpm install babel-preset-latest -D
配置文件
.babelrc
{
“presets”: “latest”
}
使用
将es6代码转码并输出到控制台
babel 1-es6.js
将es6代码转码并输出到新的文件
babel 1-es6.js --out-file 1-es5.js 简写:babel 1-es6.js -o 1-es5.js
将es6代码转码并输出到新的文件夹
babel src --out-dir dist 简写:babel src -d dist
4.模块化机制
1)CommonJS模块化规范
导入

    let { firstName, lastName } = require('./1-module.js')
    等同于
    let obj = require('./1-module.js')
    let first = obj.firstName;
    let last = obj.lastName;
    对象解构(模式匹配)
    let data = {
      username: '张三',
      age: 12
    }
    let { username, age } = data
  导出
    let name = 'zhangsan'
    let num = 1
    module.exports = {
      name,
      num
    }

(2)AMD模块化规范
AMD是"Asynchronous Module Definition"的缩写,意思就是"异步模块定义"。
它采用异步方式加载模块,模块的加载不影响它后面语句的运行。所有依赖这个模块的语句,
都定义在一个回调函数中,等到加载完成之后,这个回调函数才会运行。
3)ES6模块化规范
导入

    import { firstName, lastName, a, post } from './module1.js';
    import { firstName as first, lastName as last } from './module1.js';
    导入默认
    import data from './module1.js'
    导入全部
    import * as data from './module1.js';
    导入执行(模块加载)
    import './module1.js';
    导入第三方模块(去项目的根目录找node_modules)
    import 'babel-preset-latest';
  导出
    export { firstName, lastName };
    export { firstName as fist, lastName as last };
    export let a = 1;
    export function post() {

    } 
    默认导出(一个模块有且只能有1个默认导出,默认导出与普通导出可以共存)
    export default {

    }

CommonJS与ES6模块化规范区别
CommonJS
· 对于基本数据类型,属于复制。即会被模块缓存。同时,在另一个模块可以对该模块输出的变量重新赋值。
· 对于复杂数据类型,属于浅拷贝。由于两个模块引用的对象指向同一个内存空间,因此对该模块的值做修改时会影响另一个模块。
· 当使用require命令加载某个模块时,就会运行整个模块的代码。
· 当使用require命令加载同一个模块时,不会再执行该模块,而是取到缓存之中的值。也就是说,CommonJS模块无论加载多少次,都只会在第一次加载时运行一次,以后再加载,就返回第一次运行的结果,除非手动清除系统缓存。
· 运行时加载
ES6
· ES6模块中的值属于【动态只读引用】。
· 对于只读来说,即不允许修改引入变量的值,import的变量是只读的,不论是基本数据类型还是复杂数据类型。当模块遇到import命令时,就会生成一个只读引用。等到脚本真正执行时,再根据这个只读引用,到被加载的那个模块里面去取值。
· 对于动态来说,原始值发生变化,import加载的值也会发生变化。不论是基本数据类型还是复杂数据类型。
· 编译时输出接口。

二、ES6-基础部分

1.变量/常量声明
let 声明变量
const 声明常量
特性
. 变量声明不会被提升,即在变量声明之前无法使用该变量
. 具有局部作用域,即let声明的变量只能在对应代码块中使用
. 不允许重复声明。
. const声明的变量在声明的时候就需要赋值,并且只能赋值一次,不能修改。
2.解构(模式匹配)
1)介绍:ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值。
2)数组解构

  let [a, b, c] = [1,2,3]
  let [a, b] = [1,2,3]
  使用拓展运算符(用在=左边聚合作用,返回一个新数组)
    let [a, ...b] = [1,2,3]  // b = [2, 3]
  设置默认值
    let [a=1] = []
    let [a=myFun()] = []
3)对象解构
  let { user:user, age:age} = {user:'zhangsan',age:12}
  let { user, age } = {user:'zhangsan',age:12}
  设置默认值
    let { a, b=3} = {1}
4)字符串解构
  数组解构:从字符串里提取字符
    let [a, b, c] = 'hello'; a='h' b='e' c='l'
  对象解构:从字符串原型中解构属性和方法
    let { length, toString } = 'hello' 
5)number解构
  let { valueOf } = 12   valueOf === Number.prototype.valueOf()
6)boolean解构
  let { valueOf } = true valueOf === Boolean.prototype.valueOf()

3.对象
简写

  let name = "zhangsan";
  let obj = {
    name,
    sayName() {}
  }
API拓展
  Object.is(a,b)     判断a,b两个值是否一样,类似于===
  Object.assign() 深复制或者合并对象
  Object.assign(obj1, obj2) 深复制,将obj2复制给obj1
  Object.assign(obj1, obj2, obj3) 对象合并,将obj2、obj3合并后复制给obj1
  Object.setPrototypeOf(obj1, obj2)  为目标对象设置原型,将obj2设置成obj1的原型
  Object.getPrototypeOf(obj1)  获取目标对象的原型
  Object.keys()     返回对象属性名组成的数组
  Object.values()   返回对象属性值组成的数组
  Object.entries()  返回对象[属性名, 属性值]组成的二维数组

4.数组
拓展运算符
…用在=左边,聚合的作用(对象、数组的解构)
…用在=右边,展开(剥离)的作用
let obj1 = {
name: ‘张三’
}
let obj2 = {
…obj1,
age: 12
}
API拓展

  Array.from()  将其他类型数据(可迭代的)转成数组
  Array.of()    创建数组实例,实参就是数组的元素
  Array.prototype.find() 返回满足条件的第一个元素,参数为函数
  Array.prototype.findIndex() 返回满足条件的第一个元素的索引,参数为函数
  Array.prototype.includes()  判断当前数组中是否包含某个元素,参数为元素,返回true/false
  Array.prototype.fill()      填充数组(所有元素填充),修改数组原值
  Array.prototype.()      索引的迭代器对象
  Array.prototype.values()    元素的迭代器对象
  Array.prototype.entries()   键值对的迭代器对象

三、ES6-函数,迭代器,集合

1.函数
1)函数参数

  默认值
    let fuc = (a,b,c=0) => {}
    fun(1,2)
  解构
    let fun1 = ({ name, age, gender='male'}) => {}
    fun1({name:'zhangsan',age:12})
    let fun2 = ([a,b,c]) => {}
    fun2([1,2,3])
2)rest参数,聚合实参,返回数组(拓展运算符的逆运算)
  let fuc = (a,...b) => {
    console.log(a,b) // 1 [2,3,4,5]
  }
  fun(1,2,3,4,5)
3)箭头函数
  this指向
    普通函数:this指向调用者,没有调用者指向global
    箭头函数:没有自己的this,this指向'声明时'外部作用域的this
  箭头函数写法
    极简写法(形参只有一个时,可省略括号,只有一句返回语句时,箭头后面可直接写表达式)
      let result = arr.filter(item => item > 5)
    箭头函数完整写法=>
      let result = arr.filter((item) => {
        retrun item > 5
      })
    ES5写法=>
      let result = arr.filter(function(item) {
        retrun item > 5
      })

2.迭代器Iterator
实现了iterator接口的数据,即是可迭代的数据
1)访问

  {value: 1, done: false}
  {value: 2, done: false}
  {value: undefined, done: true}
  iterator.next() 
    通过调用.next方法,可以使迭代器对象中的指针向下移一位
    value有值,done就为false
    value为undefined时,done为true
2)作用
  1)为实现了iterator接口的数据,提供统一的访问机制(for of循环)
  2)数据内部成员按照一定的次序排列,通过调用.next()方法,指向下一个成员
  3)供ES6中的for of 循环来消费
3)for of 使用,可以遍历实现了iterator接口的数据
  let entry = arr.entries();
  for (let en of entry) {
    console.log(en);
  }
4)for of 实现(.next())
  let result;
  while (!(result = entry.next()).done) {
    console.log(result.value);
  }
5)原生具备 Iterator 接口的数据结构如下
  Array、Map、Set、String、arguments、NodeList 等

3.Set集合
类似于数组,key和value是相同

1)特性:
  不允许重复值出现
  应用:数组去重
  Array.form(new Set(arr))
2)API
  Set.prototype.size		返回Set实例的成员总数。
  Set.prototype.add(value)	添加某个值,返回Set结构本身
  Set.prototype.delete(value)	删除某个值,返回一个布尔值,表示删除是否成功。
  Set.prototype.has(value)	返回一个布尔值,表示该值是否为Set的成员。
  Set.prototype.clear()	清除所有成员,没有返回值。
  Set.prototype.keys()	返回键名的遍历器
  Set.prototype.values()	返回键值的遍历器
  Set.prototype.entries()	返回键值对的遍历器
  Set.prototype.forEach()	使用回调函数遍历每个成员

4.Map集合
类似于对象,key-value对应的集合。
1)特点:
key值不局限于字符串,可以是任意数据类型
2)API

  Map.prototype.size	返回 Map 结构的成员总数。
  Map.prototype.set(key, value)	set方法设置键名key对应的键值为value,然后返回整个map结构。如果key已经有值,则键值会被更新,否则就新生成该键。
  Map.prototype.get(key)	get方法读取key对应的键值,如果找不到key,返回undefined。
  Map.prototype.has(key)	has方法返回一个布尔值,表示某个键是否在当前 Map 对象之中。
  Map.prototype.delete(key)delete方法删除某个键,返回true。如果删除失败,返回false。
  Map.prototype.clear()	清除所有成员,没有返回值
  Map.prototype.keys()	返回键名的遍历器
  Map.prototype.values()	返回键值的遍历器
  Map.prototype.entries()	返回键值对的遍历器
  Map.prototype.forEach()	使用回调函数遍历每个成员

四、ES6-类,Symbol

1.class类
1)介绍
ES6 提供了更接近传统语言的写法,引入了 Class(类)这个概念,作为对象的模板。
通过class关键字,可以定义类。ES6 的class可以看作是构造函数一个语法糖
语法糖:具有特殊功能的代码写法,内部封装了一些方法,让一些复杂代码的编写及其用法变得简单
2)构造器
constructor方法是类的默认方法,通过new命令生成对象实例时,自动调用该方法。
一个类必须有constructor方法,如果没有显式定义,一个空的constructor方法会被默认添加。

  class Person{
    constructor(name,age){
      this.name = name;
      this.age = age;
    }
  }
3)实例方法、属性
  定义在类体中的方法称为实例方法。如下,sayName方法就是实例方法,
  本质上该方法应该是声明在Person.prototype中,可供所有的实例调用,因此称为实例方法。
  class Person{
    constructor(name,age){
      this.name = name;
      this.age = age;
    }
    sayName(){
      console.log("i am ",this.name);
    }
  }
4)静态方法、属性
  通过static关键字来定义静态属性和静态方法。
  静态属性和静态方法是定义在类【构造函数】上的,所以可以通过类【构造函数】直接访问。
  在静态方法中,this指向当前类【构造函数】
  class Person{
    static num = 200;
    static number(){
      return this.num;
    }
  }
  console.log(Person.number());	//200
5)继承
  ES5继承
    借用构造函数继承
      function Animal() {}
      function Dog() {
        Animal.call(this)
      }
    原型链继承
      子构造函数的原型指向父构造函数的实例
      Dog.prototype = new Anmimal()
  ES6继承
    用法
      class Dog extends Anmimal {
        constructor(name,age,weight) {
          super(name,age);
        }
      }
      let dog = new Dog('二狗',1,'10KG')
    子类继承父类(构造函数继承,继承静态方法、属性)
      子类的构造函数继承父类的构造函数
      子类构造函数的原型对象指向父类构造函数
      Dog.__proto__ === Animal
    子类原型对象继承父类原型对象(方法继承,继承实例方法、属性)
      Dog.prototype.__proto__ === Animal.prototype
      dog.__proto__.__proto__ === Animal.prototype

2.Symbol
1)介绍
ES6 引入的一种新的原始数据类型Symbol,表示独一无二的值。
Symbol函数可以接受参数,表示对于这个唯一值的描述。
2)使用
Symbol()函数会返回symbol类型的值
let s = Symbol()
typeof s ; //’symbol’
symbol类型的值是独一无二的
在对象中使用symbol
用于对象的属性名,就能保证不会出现同名的属性。
这对于一个对象由多个模块构成的情况非常有用,能防止某一个键被不小心改写或覆盖
let sy1 = Symbol();
obj[sy1] = ‘hello’
let obj2 = {
…obj1,
// key为变量时,需要用[]包裹
[sy1]: ‘world’
}
3)Symbol.for(key)
和 Symbol()不同的是,用Symbol.for()方法创建的symbol会被放入一个全局symbol注册表中。
并不是每次都会创建一个新的symbol,它会首先检查给定的 key 是否已经在注册表中了。
假如是,则会直接返回上次存储的那个。否则,它会再新建一个。
比如:调用Symbol.for(“cat”)30 次,每次都会返回同一个 Symbol 值,但是调用Symbol(“cat”)30 次,会返回 30 个不同的 Symbol 值。
如果想要用同一个变量,可以使用Symbol.for(‘name’)注册一个全局的,下次如果要获取该symbol值,则再次Symbol.for(‘name’)

4)Symbol.keyFor(sy1)  
  检测symbol值是否在全局登记过,返回key或者undefined。
  返回一个已登记的 Symbol 类型值的 key ,用来检测该字符串参数作为名称的 Symbol 值是否已被登记。

5)应用:消除魔术字符串:
  魔术字符串指的是,在代码之中多次出现、与代码形成强耦合的某一个具体的字符串或者数值。
  风格良好的代码,应该尽量消除魔术字符串,改由含义清晰的变量代替。
  let baseUrl = 'http://234.234.234.434:7788'
  $.get(baseUrl+'/user/findAll')
  $.post(baseUrl+'/user/saveOrUpdate')

五、ES6-异步实现编程

ES5异步编程的解决方案

$.ajax({
  url,
  method,
  data,
  success(res) {
    console.log(res)
    $.ajax({
      url,
      method,
      data: res.data[0].id,
      success() {
      
      }
    })
  }
})

1.Promise
Promise 是异步编程的一种解决方案,比传统的解决方案(回调函数和事件)更合理和更强大。
它由社区最早提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了Promise对象。
所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。
Promise对象,可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。
Promise对象提供统一的接口,使得控制异步操作更加容易。
1)创建Promise实例
// 实例化
Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject,它们是两个函数
Promise对象代表一个异步操作有三种状态: pending(进行中)、fulfilled(已成功)和rejected(已失败)。
状态发生改变之后就凝固了,不会再变了,会一直保持这个结果,这时就称为 resolved(已定型)

  let promise = new Promise((resolve, reject) => {
    if(1 > 0) {
      // pending => fulfilled
      resolve('success');
    } else {
      // pending => rejected
      reject('error')
    }
  })
  // 访问promise实例内部的状态
  promise.then(res => {
    console.log(res)
  }).catch(error => {
    console.error(error)
  })

2)实例方法
  .then()
    // promise状态为fulfilled
    参数:函数,函数内部的参数是resolve传过来的实参
  .catch()
    // promise状态为rejected 
    参数:函数,函数内部的参数是reject传过来的实参
  .finally()
    无论promise状态是成功还是失败,都会执行里面的代码
3)静态方法
  Promise.all([pro1,pro2])
    将pro1和pro2包装成数组作为实参传递进去
    返回值:promise对象。结果 =》pro1,pro2都成功才成功,有一个失败就失败
  Promise.race([pro1,pro2])
    将pro1和pro2包装成数组作为实参传递进去
    返回值:promise对象。结果 =》pro1,pro2谁先回来就用谁都结果(无论成功或者失败)
  Promise.any([pro1,pro2])
    将pro1和pro2包装成数组作为实参传递进去
    返回值:promise对象。结果 =》pro1,pro2都失败才失败,有一个成功就成功
  Promise.resolve()
    参数:任意
    返回值:状态为fulfilled的promise对象
  Promise.reject()
    参数:任意
    返回值:状态为rejected的promise对象

2.Generator
是ES6的异步编程解决方案
类似于状态机,内部封装了多个状态
返回值:迭代器对象
通过调用.next()方法,访问迭代器对象内部的状态

使用:
  function* genFun() {
    let result = yield 'one'

    console.log(result); // hello
    yield 'two'

    retrun 'others'
  }
  let gen = genFun(); // gen是generator函数返回的迭代器对象
  gen.next();
  gen.next('hello')

3.async
async函数是generator函数的语法糖
是ES6的异步编程解决方案
关键字

  function关键字前加上 async(异步)
  异步请求之前,加上 await(等待)
使用
  async function findAll() {
    let result = await $.get('......');
    console.table(result.data)
  }

        let obj = {
            name: '强强',
            mian: [10, 20],
            fn: function () {
                console.log(111);
            },
            old: {
                one: '意义',
                two: "带来"
            }
        }
        // 说明一个函数
        function copy(obj) {
            var newobj = null;
            //通过typeof判断是否为引用数据类型且不等于null    注意typeof (null)===object 
            if (typeof (obj) === 'object' && obj !== null) {
                // 三元表达式 来判断储存的类型
                newobj = obj instanceof Array ? [] : {}
                //循环obj 中的每一项,如果里面还有复杂数据类型,则直接利用递归再次调用copy函数
                for (const key in obj) {

                    newobj[key] = copy(obj[key])

                }
                // 为基本就直接赋值
            } else {
                newobj = obj
            }
            return newobj
        }
        let att = new copy(obj)
        att.mian[0] = 555
        console.log(obj);
        console.log(att);

你可能感兴趣的:(前端,前端JS\TS,javascript,开发语言,es6)