ES6必知大全

245 阅读13分钟

1,ES6基本介绍

  ES6的全称是:ECMAScript6.0,是 JavaScript 语言的下一代标准;它包含了一些很棒的新特性,可以更加方便的实现很多复杂的操作,提高开发人员的效率。目前流行的js框架都使用了大量的ES6语法。

2,ES6常用变量

  var,let,const(常量)都可以用来定义变量,以下详细介绍let与const。
1,let变量
与var类似,用来定义变量。
区别如下:
(1)块级作用域(第三种作用域)。let所声明的变量,只在let命令所在的代码块内有效。

(2)let没有“变量提升”现象。
(3)不会成为window对象的属性
(4)暂时性死区(TDZ)
2,const常量
const大多数都是来定义常量的
常见特点:
(1)声明常量。值不能改变。

(2)必须立即初始化
(3)不能够重复声明且不存在提升现象
(4)变量在栈区中的值不能改变,保存的数据在堆区的信息是可以改动的

3,ES6的字符串扩展

(1)trim起作用时并不影响原字符串。
   trim:去掉字符串左右的空格
   trimLeft:去掉字符串左边的空格
   trimRigth:去掉字符中右边的空格
(2)模板字符串
 格式如下:

(3)repeat用来指定此时重复的内容
 格式:字符串.repeat(n),这里的n代表字符串被指定的重复的次数
(4)includes表示是否包含子串
 格式:字符串.includes(子串)
(5)startsWith表示是否以子串开始
 格式:字符串.startsWidth(子串)
(6)endsWith表示是否以子串结束
 格式:字符串.endsWidth(子串) 其返回值是 true | false
(7)padStart是在字符串的前面进行填充,以达到指定的长度。
 格式:字符串.padStart(指定的长度,字符)
(8)padEnd是在字符串的后面进行填充,以达到指定的长度。
 格式:字符串.padEnd(指定的长度,字符)

4,ES6的数组扩展

1,方法的一些概念
(1)方法与函数区别与联系在于:方法也是函数,只不过写在对象里面的函数称为方法。
(2)方法分类可分成实例方法和类方法。

  • 实例方法:挂在对象上的方法;如window.alert();var obj = {init:function(){}} obj.init()。
  • 类方法:直接挂在类上的方法(构造器);如isArray

2,ES5数组新增方法
1)Array.isArray:判断一个数据是否是数组。
其格式:

Array.isArray(arr)       通过console.log()来打印出:true 或 flase。  

注意点:
(1)Array叫做构造器(本质是一个函数)。
(2)arguments(收集实参)不是一个真实的数组,长得虽然像数组,但叫伪数组或者类数组。
(3)rest参数是一个真实的数组。
2)forEach:对数组进行循环。(之前我们也会用for对数组进行循环,用for会麻烦一些,因为它要用循环变量)
其格式:

数组.forEach( function(item,index,arr){
        // 第一个参数 item : 当前的数组元素。相当于arr[index];	  
        // 第二个参数 index:数组元素的索引;
        // 第三个参数 arr 当前的数组。
     });
    item,index,arr这叫形参,形参的命名是任意的,但一般我们写的形参要见名知意,这并不影响结果。更重要的是形参的位置顺序。

注意点:
(1)形参是一个回调函数;
(2)修改item的值并不影响原数组(这有个前提,这个item的值是基本数据类型,即如果它是引用数据类型,则这个修改会影响原数组)
(3)不能break;
(4)没有返回值;
(5)如果在回调函数中你不需要用到全部的三个参数,你按顺序去省略。
3)map(map是JS内置的方法): 逐一处理原数组元素,返回一个新数组。
其格式:

arr.map( function(item,index ,arr){
     //item : 当前的数组元素。相当于arr[index]
    //arr 当前的数组
    //index:数组元素的索引;
    return
} );

 模拟map:原来我们使用的arr.map是js内置的方法,如若使用自己写的可以在Array构造器的原型上创建一个方法。
其格式:

Array.prototype.MyMap = function(f){    
        var newArray = [];
        //处理老数组中的每一个元素,处理完后,把处理后的元素放到newArray
        for(let i=0; i<this.length; i++){
            newArray.push(f(this[i],i,this))
        }
         return newArray;
    }

易错点:map也存在着修改item的值并不影响原数组。在return语句时,一般是处理谁就返回谁。新数组因为被处理当然会发生变化,所以在打印时要注意是原数组,而非处理过的新数组
(前提条件:这个item的值是基本数据类型,即如果它是引用数据类型,则这个修改会影响原数组)
小问题:什么时候要用map?
 答:在我们需要对一个数组进行一些加工,但并不想修改原数组,只是希望在原数组基础上,得到一个新数组。
4)filter: 逐一过滤原数组元素,留下符合条件的元素得到一个新数组。
其格式:

arr.filter( function(item,index ,arr){
    // item : 当前的数组元素。相当于arr[index]
    //  index:数组元素的索引;
    //   arr 当前的数组
    return 布尔值;//值为真,表示要留下这个数据。
} );

5)reduce: (累加和的感觉)不断地将前一项和后一项的值进行运算。
(具体规则是由回调函数决定的,每次的运算会涉及两项),把前一轮运算的结果作为当前运算的前一项。返回最后结果。
其格式:

格式1: 不带初始值: 
  数组.reduce(function(prev,next){return})
格式2: 带初始值: 
  数组.reduce(function(prev,next){...},初值)。  
其中,function中第一个参数prev表示前一项,第二个参数next表示后一项。当然, 你可以改其它的变量名。reduce中的第二个参数代表初值,也就是说是加数的第一个值

6)some: 只要数组中的某一个元素符合指定的条件,就会返回真,否则返回假。
其格式:

数组.some(function(value,index,arr){return;})

7)every: 数组中的每一个元素符合指定的条件,就会返回真,否则返回假。
其格式:

数组.every(function(value,index,arr){return;})

3,ES6数组新增方法 1)Array.from:这个方法是Array构造器的静态方法,将把类数组对象转成真正的数组。
其格式:

格式1:Array.from(类数组对象);
格式2:Array.from(类数组对象,function(item,index){return;})

2)Array.of:将一组值转换为数组。与Array.from功能相似,理解用来创建数组。
其格式:

Array.of(数值);

3)find:用于找出第一个符合条件的数组元素。找不到则是undefined,注意:它是不会返回多个,只找一个,找到了就返回;如果你要把所有的满足条件的数组元素都找出来,你应该用filter()。
其格式:

arr.find(function(item,index){return 条件;})

4)findIndex: 返回第一个符合条件的数组元素的索引。找不到则是-1。
其格式:

arr.findIndex(function(item,index){return 条件;})

5)includes:判断一个元素是否在一个数组中,返回值是true或者false 其格式:

arr.includes(要判断的元素值)

6)fill:给数组填充指定值。fill方法用于空数组的初始化非常方便。已有数据会被覆盖,fill方法还可以接受第二个和第三个参数,用于指定填充的起始位置和结束位置。
其格式:

格式1:arr.fill(值)
格式2:arr.fill(值,起点,终点) 包括起点,不包括终点  

5,ES6的解构赋值

1,解构赋值的定义
  ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)。其作用是对变量进行赋值。变量的值的来源是数组或者对象。解构赋值的规则就是根据一定的模式。
2,数组的解构赋值
数组的解构赋值:数组下标位置的对应关系。
(1)按下标一一对应地去赋值:因为两边赋值的数组中数据个数一致,就按照从前往后的顺序依照下标给其赋值

(2)左右数量不等:那就要从第一个开始对数组进行赋值。如若常量一方数据较多,有剩余时,那就不用管了;就当出现没有数据可以为数组赋值时,那么它就是undefined。
(3)跳过部分 :就是给那个空格不赋值,逃过它,此处为空。
(4)默认值:就是给数组添加默认值,要是该位置有数可赋,那么它会被覆盖,要是没有值则会按照默认值输出
(5)嵌套:就是在赋值时出现数组,那就按照格式去对应即可
小结:数组的解构赋值本质上是数组位置的对应关系
3,对象的解构赋值
(1)按属性名的一一对应关系来进行赋值
(2)本质-按属性名的一一对应关系来进行赋值
(3){}中只能放键值对,如果键和值是一样,可以只写一个
(4)对象是属性的无序集合
(5)解构规则:必须要通过键名进行关联;没有键名就是undefined;对象的解构赋值的内部机制,是先找到同名属性,然后再赋给对应的变量。
(6)将现有对象的属性,赋值到某个变量
(7)沿着原型链进行
(8)函数参数中的解构赋值
函数解构赋值的详例
小结:对象的解构赋值本质上是对象键值与键值对的对应关系,它与属性存放的顺序无关,对象只是属性的无序集合。

6,ES6的对象扩展

1,和属性相关的方法:
(1)Object.getOwnPropertyDescriptor() 得到某个对象中某个属性的特征

(2)Object.defineProperty()和Object.defineProperties() 前者是精细化设置一个对象的属性,后者则是精细化设置一个对象的多个属性
格式:

Object.defineProperty(对象名,"属性名",{
    configurable:   //是否可以删除。默认为true
    writable:      //是否可以修改属性的值。默认值为true
    enumerable:   //是否可以枚举,是否可以通过for in 循环来输出。默认为true
    value:       //值。默认是undefined
})

(3)Object.getOwnPropertyNames()和Object.keys()以及Object.values() 前者是得到对象中自已内部的所有的属性,放到一个数组中;后者则是得到对象中所有的键名(包含它自己的和它原型上),放到一个数组中。再者得到对象中所有的属性值(包含它自己的和它原型上),放到一个数组中
2,和继承有关的方法:
(1)Object.create() 用于对字面量对象实现继承
(2)Object.getPrototypeOf() 得到一个对象的原型对象
(3)Object.assign()用于对象的合并,将源对象(source,除第一个以外的所有对象)的所有可枚举属性,复制到目标对象(target,第一个对象)
3,防篡改的方法:
(1)preventExtensions():不允许新增,但可以修改,也可以删除
(2)seal:密封,不允许新增、也不允许删除,但可以修改
(3)freeze:冰封,不允许新增、不允许删除,不允许修改
它本质上改变的都是精细化设置中的一些属性,configurable,writable,enumerable,value之类的。

7,ES6的函数扩展

1,参数默认值
  在ES6出现之前,不能直接为函数的参数指定默认值,而ES6 允许为函数的参数设置默认值,即直接写在参数定义的后面。

小tip: (1)参数变量是默认声明的,不必再使用let或者const再次声明
   (2)对于设置默认值后又传递了参数,那么会发生覆盖,它是从第一个开始覆盖的。
2,rest参数
rest参数它是在定义函数时使用,遵循着“你们不要了的都给我”的原则,所以rest参数必须存在于最后面;在调用函数时,把参数传给对应的变量,直到没有变量可赋时,就将其它的所有的参数传给rest。
当所有参数全部打包成数组给了rest的话,那么rest就可以取代arguments啦!
3,扩展运算符(spread)
  ES6的扩展运算符是在给多参数函数传参时,用来替代Apply,合并数组,和解构配合对赋值提供了很好的便利。扩展运算符就是三个点“…”,它可将数组拆分成一个个小元素。
(1)数组中的扩展运算符
 案例一:数组的复制(...数组表示将数组展开,分解成一个一个小的元素)

 案例二:类数组转数组

 案例三:字符串转数组
  方法一:利用字符串的split方法

  方法二:[...]使用扩展运算符

 案例四:合并数组
  方法一:数组对象的concat方法
  方法二:[...]使用扩展运算符

(2)对象中的扩展运算符
  对象中的扩展运算符用于取出参数对象的所有可遍历属性,拷贝到当前对象之中。等同于使用Object.assign方法。
  实现深拷贝方式一

let school = {name:'bjdx'};
let my = {age:{count:18},name:'yjb'};  
//把原来的my放在新对象里,用一个新的age 把原来的age也拷贝一份
let newMy = {...my,age:{...my.age}}
let all = {...school,...newMy}
my.age.count = 100;
console.log(all);


4,调用函数时…和定义函数时…是不一样的
…是拓展运算符,它的功能:用来把一个数组"打散";对于...rest,这里…称为rest运算符。它的功能:把零散的参数列表打包成一个数组。

5,箭头函数
基本的作用 :简化函数的定义
格式如下:

([param] [, param]) => {//函数体statements}

箭头函数特点:
特点1:只有一个形参时,()可不写
特点2:如有多个形参,或者没有形参,则()不能少
特点3:只有一个带return语句 {} 和 return 都可以不写
特点4:只有一个不带return语句 {} 可以不写
特点5:如果返回对象,把{} 和 return 省掉的话,需要给这个对象加()
特点6:箭头函数不能当做构造函数,也就是说不能使用new命令
特点7:不能使用arguments对象,箭头函数中没有argumetns,可以使用rest参数
特点8:箭头函数内部中不存在this,this会发生丢失(事件绑定与setinterval),可通过箭头函数解决

8,Class类

Class是ES5中构造器与原型的语法糖
(1)使用class直接来创建对象,可以代替之前书写的函数里的对象
  在class创建的对象里面都是写的函数,也就是说这些函数都是方法,那么原型上的方法也就直接在这里书写啦!方法与方法之间不使用逗号,没有键值对。

class 父类{
    constructor(name,age){
        this.name = name;
        this.age = age;
    }
    method(){  //对象中简写方法,省略了function。不要与箭头函数搞混了。
    }
}

(2)使用extends实现继承,在子类中的构造器constructor中,必须要显式调用父类的super方法,如果不调用,则this不可用

class 子类 extends 父类{
    constructor(name,age){
      super(name,age)
    }
}

  实例指的是new上的东西,我们可以通过new上一个对象来调用方法,还可以通过类来调用方法,如果使用类来调用方法的话,叫静态方法。
静态方法和静态属性就只能类来调用,实例(就是new上的那个对象)不能调用

class Animal{
    static m = 1;//这里的m并不是变量而只能称之为属性
    //静态方法就仅仅是在其前面加上static,且不能使用实例调用
    static eat(){
        console.log("eat...")
    }
}
 Animal.eat()