最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • js面试三之ES6

    正文概述 掘金(前端_阿珂)   2021-07-04   488

    一、变量相关(let、var、const、function)

    let、const 与 var 的区别(五个):

    2.变量提升---把当前作用域中所有带var、function关键字的进行提前的声明和定义 【预解析】

    • var 会提升变量的声明到当前作用域的顶部; let、const 不存在变量提升.

    3.块级作用域

    4.暂时性死区

    • 只要作用域内存在 let、const,它们所声明的变量或常量就自动“绑定”这个区域,不再受到外部作用域的影响,let、const 存在暂时性死区
    var name='jack';
    {
     name='bob';
     let name;    //Uncaught ReferenceError: Cannot access 'name' before initialization
    }
    

    5.window 对象的属性和方法:

    二.模板字符串

    • 模板字符串用反引号表示,可以在里面直接使用字符串,还可以使用变量、表达式通过${}注入
    • 模板字符串中,所有的空格、换行或缩进都会被保留在输出之中

    三.箭头函数

    1.箭头函数的结构

          const/let 函数名 = 参数 => 函数体
          const add = () => {};
    

    2.箭头函数简化---- 单个参数可以省略圆括号,单行函数体可省略花括号及return

    3.this 指向

    1.全局作用域中的 this 指向
         console.log(this); // window
    
    2.一般函数(非箭头函数)中的 this 指向
          // 'use strict';
          function add() {
            console.log(this); 
            // 严格模式就指向 undefined
            // undefined->window(非严格模式下)
          }
          add();
         
         
    3.点击事件的this指向
          document.onclick = function () {
             console.log(this);  //this指向document
           };
       
          // 只有在函数调用的时候 this 指向才确定,不调用的时候,不知道指向谁
          // this 指向和函数在哪儿调用没关系,只和谁在调用有关
          // 没有具体调用对象的话,this 指向 undefined,在非严格模式下,转向 window
          
    4.箭头函数中的 this 指向
        箭头函数没有自己的 this,所以会从上级上下文一层一层的往外找this,最后找到window,他的this指向window
    

    4.不适用箭头函数的场景

    • 1.箭头函数不能作为构造函数
    • 2.需要 this 指向调用对象的时候,不能用箭头函数
        document.onclick = function () {
          console.log(this);
        };
        document.addEventListener(
          'click',
          () => {
            console.log(this); //window
          },
          false
        );
      
    • 3.需要使用 arguments 的时候,不能用箭头函数,箭头函数中没有 arguments

    四.解构赋值

    4.1 数组解构赋值(索引值相等和模式匹配)

    4.1.1 默认值,没有解构出来,就用默认值(惰性求值)

    4.1.2 数组解构赋值应用

    • 1.常见的类数组的解构赋值

    • 2.函数参数的解构赋值

    • 3.交换变量的值

    4.2 对象解构赋值(模式匹配和属性名相同)

    //属性名相同的完成赋值,可以取别名
          const { age, username: uname } = { username: 'Alex', age: 18 };
          console.log(age, uname);//解构赋值之后再赋值给uname
    
    • 默认值和数组的一样

    • 如果将一个已经声明的变量用于对象的解构赋值,整个赋值需在圆括号中进行,防止被当成块级作用域

       let x = 2;
      ({ x } = { x: 1 });
      console.log(x);    //1
      

    对象解构赋值的应用

    • 1.函数参数的解构赋值
         const PersonInfo = (user) => console.log(user.username, user.age);
         PersonInfo(({ age, username: username } = { username: "alex", age: 18 })); //alex 18 使用了解构后的值
         
         const person = ({ age = 0, username = "ZhangSan" }) =>console.log(username, age);
         person({}); //ZhangSan 0  使用了默认值
         person({ username: "alex", age: 18 }); //alex 18 使用了解构后的值
    
    • 2.复杂的嵌套

    4.3 字符串的解构赋值

    • 字符串可以按照数组形式的解构赋值
    • 字符串可以按照类数组对象形式的解构赋值(可以按照索引值和length)

    五.对象字面量增强

    5.1 属性和方法简写

    在对象中属性名和值相等可以简写;方法可以直接写,也不用function声明

    const age=18
    const obj={
                age,
                fn(){}
     }
    

    5.2.方括号语法增强--属性名可以写变量啦

          const name = 123;
          const obj = {
            ["age"]: 18,
            [name]: "蔡徐坤",
          };
          console.log(obj);//{123: "蔡徐坤", age: 18}
    

    六、函数参数默认值-可以给形参设置默认值,不传参则使用默认值

    七.剩余参数与展开运算符

    剩余/扩展运算符同样也是ES6一个非常重要的语法,使用3个点(...),后面跟着一个含有iterator接口的数据结构

    7.1 剩余参数--参数变数组

    剩余参数可以将多余的实参组成一个数组,可以在函数形参的最后一个位置通过...args设置,

    7.1.1 箭头函数的剩余参数

    7.1.2 剩余参数的应用

    • 1.完成 add 函数
    • 2.与解构赋值结合使用

    7.2 数组展开运算符---将一个数组转为用逗号分隔的参数序列,主要用于函数调用。

    console.log(Math.min(...[3, 1, 2]));
    

    7.2.1 替代函数的 apply 方法

    由于扩展运算符可以展开数组,所以不再需要apply方法,将数组转为函数的参数了,apply方法第二个参数是数组实参。

    7.2.2 数组展开运算符的应用

    • 1.复制数组(深拷贝)
           const a = [1, 2];
           const c = [...a];
           a[0] = 3;
           console.log(a);//[3,2]
           console.log(c);//[1,2]
    
    • 2.合并数组(浅拷贝)
    const arr1 = ['a', 'b'];
    const arr2 = ['c'];
    const arr3 = ['d', 'e'];
    
    // ES5 的合并数组
    arr1.concat(arr2, arr3);
    // [ 'a', 'b', 'c', 'd', 'e' ]
    
    // ES6 的合并数组
    [...arr1, ...arr2, ...arr3]
    // [ 'a', 'b', 'c', 'd', 'e' ]
    
    • 3.字符串转为数组
           console.log([...'alex']);//['a','l','e','x']
           console.log('alex'.split(''));//es6之前
    
    • 4.常见的类数组转化为数组
        4.1 arguments
           function func() {
             console.log([...arguments]);
           }
           func(1, 2);
    
        4.2 NodeList
          console.log([...document.querySelectorAll('p')]);
    
      1. 实现了 Iterator 接口的对象
    let nodeList = document.querySelectorAll('div');
    let array = [...nodeList];
    

    7.3 对象展开运算符的基本用法

    对象的扩展运算符(...)用于取出参数对象的所有可遍历属性,拷贝到当前对象之中。

    1. 展开对象(深拷贝对象)

    • 对象不能直接展开,必须在 {} 中展开
    • 对象的展开:把属性罗列出来,用逗号分隔,放到一个 {} 中,构成新对象
          const apple = {
            color: "红色",
            shape: "球形",
            taste: "甜",
          };
          const Ob = { ...apple };
          console.log(Ob);
          console.log(Ob === apple); //false
    

    2.合并对象,后面的同属姓名会覆盖前面的

    3. 用户参数和默认参数合并,默认参数写前面,用户参数写后面

    4.注意事项---如果展开的不是对象,则会自动将其转为对象,再将其属性罗列出来,类数组对象

    八.Symbol唯一值

    //1.需要使用Symbol()函数初始化
     let name1 = Symbol('liming');
     let name2 = Symbol('liming');
     console.log(name1 == name2);  //false
     
    // 希望能够多次使用同一个symbol值
     let name1 = Symbol.for('name'); //检测到未创建后新建
     let name2 = Symbol.for('name'); //检测到已创建后返回
     console.log(name1 === name2); // true
     
    //能够访问的方法:Object.getOwnPropertySymbols.该方法会返回一个数组,成员是当前对象的所有用作属性名的Symbol值。
    
     let id = Symbol("id");
     let obj = {
      [id]:'symbol'
     };
    let array = Object.getOwnPropertySymbols(obj);
     console.log(array); //[Symbol(id)]
     console.log(obj[array[0]]);  //'symbol'
    

    九.Set 和 Map 数据结构

    9.1 Set数据结构---类似于数组( value = key),但没有重复的值。

    Set 构造函数的参数--可以接受一个数组(或者具有 iterable 接口的其他数据结构如字符串、arguments、NodeList、Set)作为参数,用来初始化。

          var s2 = new Set([1, 2, 3]); 
          console.log(s2, typeof s2);   //Set(3) {1, 2, 3} "object"
    
    // 1. add添加成员(可以连写)
          const s = new Set();
          s.add(1).add(2).add(2);
          console.log(s);//{1,2}
          
    // 2. has判断是否有某个成员
          const s = new Set(["ccc", "ssss", "dddd"]);
          console.log(s.has("dddd")); //true
          
    // 3.delete删除某个成员
          s.delete("dddd");
          
    // 4. clear全部清除
          s.clear();
          
    // 5.属性size--用来获取成员个数,相当于length
    
    // 6.遍历操作(四个方法),Set 中 value = key
        // Set.prototype.keys():返回键名的遍历器
        // Set.prototype.values():返回键值的遍历器
        // Set.prototype.entries():返回键值对的遍历器
        /*  
            Set.prototype.forEach():使用回调函数遍历每个成员,有两个参数,
            第一个是回调函数,第二个是改变this指向
        */
            const s = new Set(["蔡徐坤", "李易峰", "易烊千玺"]);
            s.forEach(function (value, key, set) {
              console.log(this);//document
              console.log(value, key, set === s);//蔡徐坤 蔡徐坤 true
           }, document);
          // 按照成员添加进集合的顺序遍历
    

    Set 应用

    1.数组去重

      console.log([...new Set([1, 2, 1])]);
    
           const s = new Set('abbacbd');
           console.log(s);//{'a','b','c','d'}
           console.log([...s].join(''));
           console.log(s);
    
           //一行搞定
           console.log([...new Set('abbacbd')].join(''));
    
     <p>1111</p>
     <p>22222</p>
     <p>3333</p>
          // for()
          const s = new Set(document.querySelectorAll('p'));
          console.log(s);
          s.forEach(function (elem) {
            console.log(elem);
            elem.style.color = 'red';
            elem.style.backgroundColor = 'yellow';
          });
    

    十.Iterator 和 for...of 循环

    10.1 Iterator遍历器(迭代器)

    10.2 为什么需要 Iterator 遍历器--for..of 来遍历

    我们之前的遍历方法是:

    • 遍历数组:for 循环和 forEach 方法
    • 遍历对象:for in 循环

    而 Iterator 遍历器是一个统一的遍历方式,使用 Iterator 封装好的 for..of 来遍历,不管是数组还是对象都可以遍历

    10.3 原生可遍历(有Iterator接口)

    • 一般的对象可以用for ... in遍历,也可以给他添加一个Symbol.iterator然后用for ... of 遍历

    10.2.1 for...of 遍历数组

    const arr = [1, 2, 3];
    //1.遍历出索引值arr.keys() 得到的是索引的可遍历对象
          for (const key of arr.keys()) {
              console.log(key);
           }
    //2.遍历出值arr.values() 可以等价于arr
    //3遍历出[index,value]用arr.entries() 得到的是索引+值组成的数组的可遍历对象
    

    10.2.2 for...of 遍历普通对象Object.entries(obj)

    十一.Es6新增方法

    11.1 Es6字符串新增方法(3个)

    1. includes()判断字符串中是否含有某些字符

    //判断字符串
    console.log('abc'.includes('a', 0));//true
    1.第一个参数------表示是否包含该值
    2.第二个参数----- 表示开始搜索的位置,默认是 0,index
    
    //判断数组
     arr = ["name", 2, 3, 4, 5, 6, 7, 8];
     console.log(arr.includes("name"));//true
    
    应用:给url添加参数,判断url有没有问号,有问号说明有key=value,再添加就直接添加连接符&key=value

    2.padStart() 和 padEnd()在字符串本身的头部或尾部补全字符串长度

          console.log("abc".padStart(10, "0123456789")); //0123456abc
          console.log("abc".padEnd(10, "0123456789")); //abc0123456
          //  第一个参数表示补全后的字符串长度(有几个),第二个参数是要用到的元素补全字符串
          // 如果省略第二个参数,默认使用空格补全长度
    
    应用----显示日期格式

    3.trimStart() 和 trimEnd()清除字符串的首或尾空格

           const s = '  a b c  ';
           console.log(s);
           console.log(s.trimStart());
           console.log(s.trimEnd());
    
    应用-表单验证提交

    11.2 Es6数组新增方法(三个)

    1.includes()

    • 判断数组中是否含有某个成员
    • 第二个参数表示搜索的起始位置,默认值是 0
    应用-数组去重
          const arr = [];
          for (const item of [1, 2, 1]) {
            if (!arr.includes(item)) {
              arr.push(item);
            }
          }
          console.log(arr); //[1,2]
    

    2.Array.from()将类数组对象或可迭代对象转化为数组

    • 一个类数组对象必须含有 length 属性,且元素属性名必须是数值或者可转换为数值的字符。

    • 可迭代对象(数组、字符串、Set、Map、NodeList、arguments)。

    • 元素属性名不为数值且无法转换为数值,返回长度为 length 元素值为 undefined 的数组

    • 第一个参数---能被转化的数据对象。

    • 第二个参数---作用类似于数组的 map 方法,用来对每个元素进行处理,将处理后的值放入返回的数组

    • 第三个参数--第二个参数为一般回调函数时,第三个参数可以改变 this 指向

          let a = { 
              0: "aaa", 
              1: "bbb", 
              2: "cccc", 
              3: "ddd", 
              4: "eeee", 
              length: 5 
            };
          let array1 = Array.from(a, (value) => value + "你真帅");
          console.log(array1); // ["aaa你真帅", "bbb你真帅", "cccc你真帅", "ddd你真帅", "eeee你真帅"]
    

    3.find(callback)返回元素 和 findIndex()返回索引

    findIndex()用法结构类似,但是,返回数组中第一个满足条件的索引(从0开始), 不满足返回-1;

    应用-筛选数据
          const students = [
            {
              name: "张三",
              sex: "男",
              age: 16,
            },
            {
              name: "李四",
              sex: "女",
              age: 22,
            },
            {
              name: "王二麻子",
              sex: "男",
              age: 32,
            },
          ];
          console.log(students.find((value) => value.sex === "男"));
          console.log(students.findIndex((value) => value.sex === "女"));
    

    11.3 Es6对象新增方法(2个)

    1.Object.assign()合并对象

    • Object.assign(目标对象, 源对象 1,源对象 2,...): 目标对象
    • Object.assign 直接合并到了第一个参数中,返回的就是合并后的对象
    应用--合并默认参数和用户参数
          const logUser = (userOptions) => {
            const DEFAULTS = {
              username: "ZhangSan",
              age: 0,
              sex: "male",
            };
            const options = Object.assign({}, DEFAULTS, userOptions);
            console.log(options);
          };
          logUser();
    

    2.Object.keys()、Object.values() 和 Object.entries()

    • 数组的 keys()、values()、entries() 等方法是实例方法,返回的都是 Iterator
    • 对象的 Object.keys()、Object.values()、Object.entries() 等方法是构造函数方法,返回的是数组
          const person = {
            name: "Alex",
            age: 18,
          };
    
          console.log(Object.keys(person)); //['name',"age"]
          console.log(Object.values(person));//["Alex", 18]
          console.log(Object.entries(person)); //二维数组  [["name", "Alex"],["age", 18]]
    
    应用-和for...of...一起遍历对象
          obj = { name: "蔡徐坤", age: "18", hobby: ["唱歌", "写歌", "跳舞"] };
          console.log(Object.entries(obj));
    
          for (key of Object.entries(obj)) {
            console.log(key[0], key[1]);
          }
    

    十二.Promise对象

    • Promise是ES6中新增的异步编程解决方案, 他是一个构造函数,在代码中通过new Promise()生成一个实例对象。精髓是通过状态调用用对应的回调函数。
    • Promise对象可以将异步操作以同步流程来表示, 避免了回调函数层层嵌套(回调地狱)。

    12.1 基本使用

    //Promise是一个构造函数
    let p = new Promise(executor)
    
    let p=new Promise((resolve,reject)={
      /* 
      执行器函数里面,一般存放的都是我们即将要处理的异步任务(比如网络请求),任务成功我们执行resolve吧数据传出去, 任务失败我们执行reject(当然写同步的也可以),之后根据状态就可以调用原型里面的三个方法
      */
    })
    

    12.2 Promise.prototype.then()方法的使用(可以多次使用)

    • then 方法接收两个函数为参数,第一个参数是 Promise 执行成功时的回调,第二个参数是 Promise 执行失败时的回调,两个函数只会有一个被调用。

    • then()方法执行后返回的是一个新的 Promise 对象,这个promise的状态由then里面执行的回调函数的返回值决定,返回值是非promise对象,他的状态就是成功的,返回值是promise对象,状态就由这个对象决定

    // Promise对象的结构;
    {
     [[PromiseState]]: "fulfilled"
    //第一个由resolve或reject决定,后面执行的then返回的对象状态由当前函数返回值决定
             
    [[PromiseResult]]: "222"
    //结果就是当前Promise对象调用then之后return的值,
    }      
    

    12.2 Promise.prototype.catch()方法的使用

    • .catch()专门监听失败的回调
    • 如果需要分开监听,用.then().catch()方法使用链式编程,promise的状态如果是失败, 但是没有对应失败的监听就会报错
    • 和then方法第二个参数的区别在于, catch方法可以捕获上一个promise对象then方法(也包括成功的回调的方法)中的异常。

    js异常处理

    try {
      可能遇到的意外的代码
    }
    catch(e) {
      捕获错误的代码块
    }
    

    12.3 Promise.all()方法的使用

    • 应用场景: 批量加载, 要么一起成功, 要么一起失败

    12.4 Promise.race()方法的使用

    • 应用场景: 接口调试, 超时处理

    给超时函数和加载函数均包装一个promise对象,然后把这个对象写入race里面,紧接着写处理函数,5s之内没有获取资源,就直接超时处理

    12.5 Promise.resolve()和Promise.reject()方法的使用

    Promise.resolve()返回一个成功的Promise对象

          p = Promise.resolve("success");
          console.log(p);
    
          /*
          [[PromiseState]]: "fulfilled"
          [[PromiseResult]]: "success"
          */
    

    Promise.reject()返回一个失败的Promise对象

          p = Promise.reject("failed");
          p.catch((err) => console.log(err));
          console.log(p);
    
          /*
           [[PromiseState]]: "rejected"
           [[PromiseResult]]: "failed"
          */
    

    Promise封装网络请求放到网络那一块

    • 买菜(20分钟)-->做饭(30分钟)-->送饭(十分钟)-->通知;都是耗时的异步任务
    • 搞很多函数(买菜函数、做饭函数、送饭函数、亲一个函数),均接受resolve函数参数,并在定时器里面执行resolve把做好了的事情发过去。
    new Promise(买菜).then((买好的菜)=>{
        return new Promise(做饭);
    }).then((做好的饭)=>{
        return new Promise(送饭);
    }).then((送饭结果)=>{
        老婆亲一个();
    }).catch(err=>throw new Error(err))
    
    //写好任务计划表
    function 买菜(resolve,reject) {
        setTimeout(function(){
            resolve(['西红柿'、'鸡蛋'、'油菜']);
        },3000)
    }
    function 做饭(resolve, reject){
        setTimeout(function(){
            //对做好的饭进行下一步处理。
            resolve ({
                主食: '米饭',
                菜: ['西红柿炒鸡蛋'、'清炒油菜']
            })
        },3000) 
    }
    function 送饭(resolve,reject){
        //对送饭的结果进行下一步处理
        resolve('老婆的么么哒');
    }
    function 电话通知我(){
        //电话通知我后的下一步处理
        给保姆加100块钱奖金;
    }
    
    //开始做任务
    // 告诉保姆帮我做几件连贯的事情,先去超市买菜
    new Promise(买菜)
    //用买好的菜做饭
    .then((买好的菜)=>{
        return new Promise(做饭);
    })
    //把做好的饭送到老婆公司
    .then((做好的饭)=>{
        return new Promise(送饭);
    })
    //送完饭后打电话通知我
    .then((送饭结果)=>{
        电话通知我();
    })
    

    十三.async 函数

    • 1.给函数加上一个async修饰符之后,函数执行的结果是一个成功的promise对象,我们可以直接在函数执行语句后面用then。
          async function foo() {
            //1.返回成功的
            //return Promise.resolve();
            return 1;
    
            // 2.返回失败的
            // return Promise.reject();
            // throw new Error("我错了");
          }
     
          foo().then((res) => {
            console.log(res); //1
          });
    
    • 2.await只能在async函数里面执行,否则会报错,它的含义是等待一个promise实例成功后执行。
    面试题:编写一个 sleep 函数,让其等待 1000ms 后再去做其他事情?
    • 方案一:用定时器
    • 方案二:函数返回值为Promise对象
          function sleep(interval = 5000) {
            return new Promise((resolve) => {
              setTimeout(resolve, interval);
            });
          }
          sleep(2000).then(() => {
            console.log("我在2000ms之后执行");
          });
    
    • 方案三:利用await语句
          function sleep(interval = 1000) {
            return new Promise((resolve) => {
              setTimeout(resolve, interval);
            });
          }
          (async function () {
            //买菜需要八秒
            await sleep(8000);
            //菜卖回来了通知我
            console.log("我在1000ms之后执行");
            //做饭需要两秒
            await sleep(2000);
            //饭做好了通知我
            console.log("我在2000ms之后执行");
            //吃饭需要5s
            await sleep(5000);
            //吃完饭了通知我
            console.log("我在5000ms之后执行");
          })();
    

    十四.Module 的语法

    变量或函数加载

    • 若果要输出变量或函数,直接在其最前面加上export,而使用其他模块中变量时,则使用import引入
    //1.export 设置对外接口
    export var name='蔡徐坤'
    export function multiply() {}
    export { firstName, lastName, year }
    
    //import 命令加载这个模块(对外对内接口名相同)。
    //import 命令输入的变量都是只读的,不允许在加载模块的脚本里面,改写接口。
    //import 命令具有提升效果,会提升到整个模块的头部,首先执行。
    import { firstName, lastName, year } from './profile.js'
    

    模块的整体加载---export default 命令

    // export-default.js
    export default function () {
      console.log('foo')
    }
    
    // import-default.js
    import customName from './export-default'
    customName() // 'foo'
    

    起源地下载网 » js面试三之ES6

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元