JavaScript-ES6

JavaScript --ES6总结

1.var、let、const 区别

1.1作用域不同:块级作用域:声明的变量只在该代码块作用域内有效

  • var没有块级作用域,let、const有块级作用域

1.2暂时性死区

  • 只有块级作用域没有let、const命令,声明的变量绑定在这个区域内,不受外部影响

1.3变量提升:变量在声明之前使用

  • var存在变量提升,let,const不存在变量提升

1.4能否重复声明

  • var声明可以重复,会覆盖值,let、const不可以重复声明

1.5变量是否被修改

  • var、let声明的变量可以被修改,const不可以,但如果是对象,引用的地址不变,内容可以修改。
  • const声明之后必须赋值

面试问题
const声明的值一定是不可更改的吗?

const 对于简单类型的数据(数值、字符串、布尔值),值就保存在变量指向的那个内存地址,因此等同于常量。但对于复合类型的数据(主要是对象和数组),变量指向的内存地址,保存的只是一个指向实际数据的指针,const只能保证这个指针是固定的(即总是指向另一个固定的地址),至于它指向的数据结构是不是可变的,就完全不能控制了。(const的值并非不可更改

变量提升,class 声明一个类时,存在变量提升么?为什么?

ES6引入了类的概念,有了class关键字,其实是语法糖的表现,类的实质还是函数对象(腾讯云一面),但是class不存在变量提升,声明定义必须在使用之前,因为要方便类的继承,必须保证子类在父类之后定义。

const声明一个对象,如何让内部属性的值无法改变?

使用Object.freeze()锁死,冻结对象的属性不能修改,不能添加属性

2.解构赋值

阮一峰老师的解析全面又生动,强推

解构赋值语法是JavaScript的表达式,可以将属性/值从对象/数组中取出,赋值给其他变量,本质上,这种写法属于“模式匹配”,只要等号两边的模式相同,左边的变量就会被赋予对应的值。

2.1数组解构

可以从数组中提取值,按照对应位置,对变量赋值。

2.2对象解构

对象的解构与数组有一个重要的不同。数组的元素是按次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值,否则返回undefined

2.3字符串解构

字符串被转换为类似数组的对象

2.4数值和布尔值的解构

如果等号右边是数值和布尔值,则会先转为对象。只要等号右边的值不是对象或数组,就先将其转为对象。由于undefined和null无法转为对象,所以对它们进行解构赋值,都会报错。

3.展开运算符

ES6中引入三个点(…)作为展开运算符,把数组或者类数组对象展开成一系列用逗号隔开的值,除此之外还可以用作rest参数剩余运算符。

  • 复制数组:
let arr1 = [1,2,3];
let arr2 = [...arr1];
let [...arr2] = arr1//[1,2,3]
  • 合并数组
let arr1 = [1,2,3];
let arr2 = [4,5,6];
let arr3 = [7,8,9];
[...arr1,...arr2,...arr3]//[1,2,3,4,5,6,7,8,9]
  • 将字符串转换成数组
[...'xiao']//["x","i","a","o"]
  • 除了对数组操作,还可以用于对象合并

4.模板字符串

模板字符串用反引号(``)标识,可以当作普通字符串使用,也可以用来定义多行字符串,或者在字符串中嵌入变量

//普通字符串
`my name is xiao`
//多行字符串
`I am 
  xiao`
//字符串中嵌入变量,需要用${}括入变量
let name="xiao",age=18;
`My name is ${name}, i am ${age} years old`
  • 如果在模板字符串中需要使用反引号,需要用反斜杠转义。
  • 空格和换行在模板字符串中是保留的,可以用trim()去掉

5.箭头函数

ES6用()=>{}取代普通函数function(){}的方式,语法上相对更简洁,日常开发应用较多。

  • 当参数为空或者参数多个时,需要写()
let fn = a => a;
//普通函数
let fn = function(a){
	return a;
}
  • 函数体多行语句时,用{}包裹起来,表示代码块,只有一行语句,并且需要返回结果时,可以省略{}
let fn = (a,b) => {
	return a-b;
}
  • 返回对象时,需要用()把对象括起来
let fn = (a,b) => ({
	name:xiao,
	age:18
})

箭头函数和普通函数区别:

  • 外形不同:箭头函数使用()=>{}定义

  • 普通函数可以使用匿名函数,也可以有具体名函数,但是箭头函数只能是匿名函数

  • 箭头函数不能用于构造函数,不能使用new;普通函数可以,还可以创建对象实例

  • 在普通函数中,this指向调用它的对象,用作构造函数时,指向创建的对象实例;箭头函数this指向不同:
    (1)箭头函数没有prototype原型,本身没有this,在定义时可以捕获所在上下文的this,可以是全局window,也可以是继承自外层第一个普通函数的this
    (2)结合call,apply,bind使用时,只传入一个参数,对this没有影响,不能改变this指向

  • 箭头函数不能绑定arguments,但this指向普通函数时,继承普通函数的arguments,用rest参数或者命名参数的形式访问

  • 箭头函数不支持重命名函数参数,普通函数支持,后面的会覆盖前面的

  • 其他区别:箭头函数不能用于generator函数,不能使用yeild关键字;没有原型对象;不能用super

注意 面试问题:遇到浏览器不支持箭头函数的情况怎么办?

(1)script标签的type值设为:

<script type="text/babel"><script src="browser.min.js"></script>

如果问到babel原理:
babel转译分为三个阶段:parsing、transforming、generating
例如ES6转ES5:

  • ES6代码输入
  • babylon进行解析得到AST
  • plugin用babel-traverse对AST树进行遍历转译,得到新的AST树
  • 用babel-generator通过AST树生成ES5代码

(2)在头部增加polyfill.js

安装方式:
npm install babel-polifill --save

6.rest参数,arguments对象

6.1arguments参数

arguments是函数(除箭头函数)中一个比较特殊的局部变量,是函数的内置属性。

  • 所有的函数都内置一个了arguments对象,存储传递的所有实参。
  • 它只是一个伪数组,可以进行遍历,拥有length属性,但并不是真正的数组,不能调用数组的方法。
  • 可以使用数组的slice方法,Array.prototype.slice.call(arguments),转换为数组。
  • arguments的callee属性表示对当前函数的引用,可以实现匿名函数的递归

6.2rest参数

ES6引入rest参数,在参数名称前面加**…,例如…args**表示一个未知数量的参数作为函数的一个数组,因此解决了arguments的很多问题,可以正常使用数组方法。

二者区别:

  • rest参数只包含没有对应形参的实参,可以是参数的一部分,而arguments对象包含传给函数的所有实参,是参数的全部
  • arguments对象是一个伪数组,rest参数是真正的数组
  • arguments对象有附加属性,例如callee属性
  • 需要将arguments转化为数组,才可以使用数组方法
  • 箭头函数和普通函数都可以使用rest参数
  • rest参数可以自定义接受参数的数量,必须是函数最后一位参数,函数的length属性不包括rest参数

7.set、map

7.1set

set是ES6新增的叫做集合的数据结构,类似于数组,但是成员值是唯一的,本身是一个构造函数,用来生成set数据结构。(可以进行数组去重)
方法:

  • add()添加值,返回set
  • delete()删除值,返回布尔值,表示删除是否成功
  • has()判断值是否存在,返回布尔值
  • clear(),清除所有成员,没有返回值

遍历:

  • keys():返回键名
  • value():返回键值
  • entries():返回键值对
  • forEach():使用回调函数遍历每个成员

扩展运算符和Set 结构相结合实现数组或字符串去重
实现并集、交集、和差集

7.2map

map是一种叫做字典的数据结构,以键值对的形式存储,任何值(对象或者原始值) 都可以作为一个键或一个值。
属性/方法:

  • clear() :清除所有元素
  • delete(key)删除值,返回布尔值,表示删除是否成功
  • get(key):返回指定key的键值,找不到返回undefined
  • has(key):判断是否包含某个元素,返回布尔值
  • set(key,value):添加元素
  • toString():返回字符串表现形式
  • valueOf():返回指定对象的原始值
  • size属性返回成员总数

遍历:

  • keys():返回键名
  • value():返回键值
  • entries():返回键值对
  • forEach():使用回调函数遍历每个成员

map数据结构转数组,用扩展运算符(…)

8.promise

Promise是ES6中新增的一种异步编程的方式,用于解决回调的方式的各种问题,有人说promise是构造函数,有人说是对象,在JavaScript中万物皆对象。
(1)一个promise只有三个状态:

  • pending 异步任务正在进行
  • resolved(fulfilled)异步任务执行成功
  • rejected异步任务失败

(2)创建时必须传递一个参数,否则会报错;
(3)传递函数中参数是两个回调函数,resolve和reject

static resolve(value){
    if (value instanceof Promise) {
      return value;
    }
    return new Promise((resolve,reject)=>{
      resolve(value);
    })
}

static reject(value){
    return new Promise((resolve,reject)=>{
      reject(value);
    })
}

(4)状态一旦发生改变不会再发生变化
(5)同一个promise对象可以添加多个then监听,状态改变时按监听顺序依次执行
(6)then方法每次执行完毕后返回一个新的promise对象
(7)上一个Promise对象的then方法可以给返回的新的Promise的then传递参数
(8)无论上一个是在then成功或者失败的回调中传参,都会传递给新的Promise对象then方法中成功的回调
(9)如果上一个传递的是一个Promise对象,那么传给下一个的成功还是失败由传递的Promsie状态决定
(10)then返回的promise可以捕捉当前then方法的异常
(11)catch就是then方法的语法糖

class Promise{
	//....
    catch(onRejected){
    	 return this.then(null,onRejected)
    }
}

8.1promise.all

汇总多个promise的结果,异步请求并行操作:

  • 当所有的结果成功返回时按照请求顺序返回成功
  • 当其中一个失败,进入失败方法
static all(promiseArr){
	//返回新的promise实例
    return new Promise((resolve,reject)=>{
      var length = promiseArr.length
      var result = [];
      for(var i = 0;i<length;i++){
        let _promise = promiseArr[i];
        function handlerResolve(index,item){
          result[index] = item;
          //因为promise完成的时间不尽相同 所以用--length来判断合适全部处理完成
          --length;
          if(length == 0){
            resolve(result);
          }
        }
        Promise.resolve(_promise).then((value)=>{
          handlerResolve(i,value);
        },reason=>{
          //有失败则返回
          reject(reason)
          return;
        })
      }
    })
  }

应用场景:

1.多个请求结果合并在一起:一个页面有多个请求,我们需要把所有的请求都返回数据后再一起渲染;
2.合并请求结果并处理错误;
3.验证多个请求结果是否都满足条件:表单验证,多个字段,全部验证通过才可以提交

8.2promise.race

race 函数返回一个 promise,它将与第一个传递的 promise 相同的完成方式被完成。它可以是完成( resolved),也可以是失败(rejected),这要取决于第一个完成的方式是两个中的哪个。

应用场景:

1.图片请求超时;
2.请求超时提示:上一秒刷新闻,下一秒进入电梯,提示网络不佳;

static race(promiseArr){
    return new Promise((resolve,reject)=>{
      var length = promiseArr.length
      for(var i = 0;i<length;i++){
        let _promise = promiseArr[i];
        //谁先返回结果就返回谁
        Promise.resolve(_promise).then(value=>{
          resolve(value)
          return;
        },reason=>{
          reject(reason)
          return;
        })
      }
    })
 }

8.3promise.prototype.then

promise的链式调用

应用场景:

1.下一个请求依赖上个请求的结果;
2.中间件功能使用:返回接口数量比较大,在一个then里面处理显得臃肿,多个渲染数据分别给then。

8.4promise.allSettled

Promise.allSettled()方法接受一组 Promise 实例作为参数,包装成一个新的 Promise 实例。只有等到所有这些参数实例都返回结果,不管是fulfilled还是rejected,包装实例才会结束。该方法由 ES2020 引入。该方法返回的新的 Promise 实例,一旦结束,状态总是fulfilled,不会变成rejected。状态变成fulfilled后,Promise 的监听函数接收到的参数是一个数组,每个成员对应一个传入Promise.allSettled()的 Promise 实例。

static MyallSettled(promises){
   let resArr=new Array(promises.length);
   let num=0;
   retrun new Promise(resolve=>{
       promises.forEach((item,key)=>{
           let obj={};
           item.then(v=>{
               obj['status']="fulfilled";
               obj.value=v;
               resArr[key]=obj;
               num++;
               if(num===promises.length){
                   resolve(resArr);
               }
           },r=>{
               obj['status']="rejected";
               obj.reason=r;
               resArr[key]=obj;
               num++;
               if(num===promises.length){
                   resolve(resArr);
               }
           })
       })
   });
}

应用场景:

  • 彼此不依赖,其中一个被reject,对其他没有影响
  • 期望知道每个promise执行结果

9.迭代、生成

9.1迭代器iterator

迭代器是一种特殊对象,所有的迭代器对象都有一个next()方法,每次调用都返回一个结果对象。结果对象有两个属性:一个是value,表示下一个将要返回的值;另一个是done,它是一个布尔类型的值,当没有更多可返回数据时返回true。迭代器还会保存一个内部指针,用来指向当前集合中值的位置,每调用一次next()方法,都会返回下一个可用的值

如果在最后一个值返回后再调用next()方法,那么返回的对象中属性done的值为true,属性value则包含迭代器最终返回的值,这个返回值不是数据集的一部分,它与函数的返回值类似,是函数调用过程中最后一次给调用者传递信息的方法,如果没有相关数据则返回undefined

9.2生成器generator

Generator 函数,可以通过 yield 关键字,把函数的执行流挂起,为改变执行流程提供了可能,从而为异步编程提供解决方案。

Generator 有两个区分于普通函数的部分:一是在 function 与函数名之间加 * ;函数内部有 yield 表达式。其中 * 表示函数为 Generator 函数,yield 定义函数内部的状态。

一般情况下,yield表达式在next 方法不传入参数时的返回值是 undefined ,当 next 传入参数的时候,参数会作为上一步yield的返回值。yield* 表达式表示 yield 返回一个遍历器对象,用于在 Generator 函数内部,调用另一个 Generator 函数。

10.async、await

10.1async

async 是 ES7 才有的与异步操作有关的关键字,和 Promise , Generator 有很大关联的。async 函数返回一个 Promise 对象,可以使用 then 方法添加回调函数。
async声明方式:

  • 函数声明:async function fn(){}
  • 表达式声明:let fn = async function(){}
  • 对象声明:
let obj = {
	async fn(){
	}
}
  • 箭头函数声明:let fn = async() => {}

10.2await

await 操作符用于等待一个 Promise 对象, 它只能在异步函数 async function 内部使用。返回 Promise 对象的处理结果。如果等待的不是 Promise 对象,则返回该值本身。如果一个 Promise 被传递给一个 await 操作符,await 将等待 Promise 正常处理完成并返回其处理结果。

11.class

ES6引入class,使用原型对象模仿面向对象的类和继承,通过class类创建对象,可以避免重复性代码,满足面向对象的特性。两个或多个对象的结构类似,可以抽象出一个模板,依照模板复制相似的对象。(实质就是继承)

但是JS 中并没有一个真正的 class 原始类型, class 仅仅只是对原型对象运用语法糖。

function声明会存在变量提升,而class不会,需要先声明再使用

11.1constructor

constructor是一个特殊的方法,用来创建并初始化一个对象,在一个class中只能有一个命名为constructor的特殊方法,如果包含多个将会报错。

constructor中可以通过super关键字,调用父类的constructor方法。

11.2继承

ES6提供extends实现类的继承class 子类 extends 父类

class Parent{
    constructor(name,age){
        this.name=name;
        this.age=age;
    }
}

class Son extends Parent{
    constructor(name,age,score){
        super(name,age)
        this.score=score;
    }
}
  • 子类必须在constructor方法中调用super方法
  • 在调用super后才可以使用this

也就是先将父类的属性和方法拿过来,才可以继续添加自己的属性和方法

12.symbol

ES6新增数据类型

  • 实例是唯一且不可改变的,一种唯一标识符,可用作对象的唯一属性名
  • 隐藏性,作为对象属性key使用时,for…in不会遍历到symbol的key
    symbol类似一种构造函数,可以创建一个symbol对象,symbol 接收一个参数,表示对生成的 symbol 值的一种描述
let name = Symbol("name")

后续再继续补充…

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值