美文网首页前端面试题让前端飞
前端面试:ES6 基础知识点 & ES6 相关面试题

前端面试:ES6 基础知识点 & ES6 相关面试题

作者: 前小小 | 来源:发表于2021-06-21 16:56 被阅读0次

    前言

    ECMAScript 6.0(简称ES6)是 JavaScript 语言的下一代标准。它的目标,是使得 JavaScript 语言可以用来编写复杂的大型应用程序,成为企业级开发语言。

    let const

    在es6之前,定义变量都是使用var,但是var存在一些问题,比如可以重复声明,仅支持函数作用域问题。所以es6设计了let和const来弥补不足的地方。let和const具备哪些特性?

    let

    • 不能重复声明
    • 块级作用域
    • 可修改let变量的值

    const

    • 不可重复声明
    • 块级作用域
    • 不可修改const变量的值

    块级作用域

    es5只有全局作用域和函数作用域,没有块级作用域:

    var temp = new Date();
    
    function f() {
      console.log(temp);
      if (false) {
        var tmp = "hello world";
      }
    }
    
    f(); // undefined
    
    • es6的块级作用域:
    function f1() {
      let n = 5;
      if (true) {
        let n = 10;
      }
      console.log(n); // 5
    }
    
    // IIFE 写法
    (function () {
      var temp = ...;
      ...
    }());
    
    // 块级作用域写法
    {
      let temp = ...;
      ...
    }
    
    • es6中引入了块级作用域,明确允许在块级作用域之中声明函数
    // ES6严格模式
    'use strict';
    if (true) {
      function f() {}
    }
    // 不报错
    
    • es6的块级作用域声明函数只在使用大括号的情况下成立
    // 不报错
    'use strict';
    if (true) {
      function f() {}
    }
    
    // 报错
    'use strict';
    if (true)
      function f() {}
    

    扩展运算符:

    将一个数组转化为逗号分隔的参数序列

    console.log(...[1, 2, 3])               
    // 1 2 3
    
    console.log(1, ...[2, 3, 4], 5)         
    // 1 2 3 4 5
    
    [...document.querySelectorAll('div')]   
    // [<div>, <div>, <div>]
    
    {...{a: 1}, ...{a: 2, b: 3}}            
    // {a: 2, b: 3}
    
    [...[1], ...[2, 3]]                     
    // [1, 2, 3]
    
    const arr = [1]
    arr.push(...[2, 3])                     
    // arr:[1, 2, 3
    

    默认参数:

    function log(x, y = 'World') {
        console.log(x, y)
    }
    
    log('Hello')             
    // Hello World
    
    log('Hello', undefined)  
    // Hello World
    
    log('Hello', 'China')    
    // Hello China
    
    log(undefined, 'China')  
    // undefined China
    
    log(, 'China')           
    // 报错 SyntaxError
    
    log('Hello', '')         
    // Hello
    
    log('Hello', null)       
    // Hello null
    

    参数不传递或是传递 undefined 会让参数等于默认值,如果参数不是最后一个,不传递参数就会报错。

    传递null不会让函数参数等于默认值。

    // 获取函数所有的参数,rest 为数组
    function func1(...rest){ /* ... */}
    
    // 获取函数第一个参数外其他的参数,rest 为数组
    function func1(val, ...rest){ /* ... */}
    

    模板字符串:

    var str = `abcdefgh`;
    console.log(str);
    let name = "小明";
    function a() {
        return "ming";
    }
    console.log(`我的名字叫做${name},年龄${17+2}岁,性别${'男'},游戏ID:${a()}`);
    

    函数的默认参数:

    function A(a,b=1){
        console.log(a+b);
    }
    A(1);    //2
    A(2+3);  //5
    

    箭头函数:

    //省略写法
    var people = name => 'hello' + name;
     
    var getFullName = (firstName, lastName) => {
        var fullName = firstName + lastName;
        return fullName;
    }
    

    对象的扩展:

    var foo = 'bar';
    var baz = {foo};  
    //等同于  var baz = {foo: foo};
    
    var o = {
      method() {
        return "Hello!";
      }
    };
     
    // 等同于
    var o = {
      method: function() {
        return "Hello!";
      }
    };
    

    set数据结构

    • size 数据的长度
    • add() 添加某个值,返回 Set 结构本身。
    • delete() 删除某个值,返回一个布尔值,表示删除是否成功。
    • has() 查找某条数据,返回一个布尔值。
    • clear() 清除所有成员,没有返回值。

    Promise对象

    它有三种状态,分别是pending-进行中、resolved-已完成、rejected-已失败。

    var promise = new Promise((resolve, reject) => {
        var success = true;
        if (success) {
            resolve('成功');
        } else {
            reject('失败');
        }
    }).then(
        (data) => { console.log(data)},
        (data) => { console.log(data)}
    )
    

    async await

    async其实就是对Generator的封装,只不过async可以自动执行next()。

    async function read () {
        let data1= await new Promise(resolve => {
            resolve('100')
        })
        let data2 = await 200
        
        return 300
    }
    

    (1)async 返回值

    async 默认返回一个 Promise,如果 return 不是一个 Promise 对象,就会被转为立即 resolve 的 Promise,可以在 then 函数中获取返回值。

    async 必须等到里面所有的 await 执行完,async 才开始 return,返回的 Promise状态才改变。除非遇到 return 和错误。

    async function fn () {
        await 100
        await 200
        return 300
    }
    fn().then(res => {
        console.log9(res) // 300
    })
    

    (2)await

    await 也是默认返回 Promise 对象,如果 await 后面不是一个 Promise 对象,就会转为立即 resolve 的 Promise

    如果一个 await 后面的 Promise 如果为 reject,那么整个 async 都会中断执行,后面的awiat都不会执行,并且抛出错误,可以在 async的catch中捕获错误

    async function f() {
      await Promise.reject('error');
      await Promise.resolve('hello world'); // 不会执行
    }
    f().then(res =>{
    
    }).catch(err=>{
        console.log(err)  // error
    })
    

    如果希望一个await失败,后面的继续执行,可以使用try...catch或者在await后面的Promise跟一个catch方法:

    // try...catch
    async function f() {
      try {
        await Promise.reject('出错了');
      } catch(e) {
      }
      return await Promise.resolve('hello world');
    }
    
    f()
    .then(v => console.log(v))   // hello world
    
    // catch
    async function f() {
      await Promise.reject('出错了')
        .catch(e => console.log(e));   // 出错了
      return await Promise.resolve('hello world');
    }
    
    f()
    .then(v => console.log(v))  // hello world
    

    箭头函数

    箭头函数在写法上对es5做了一些修整,代码看起来更显得简洁

    • 如果只有一个参数,圆括号 "()" 可以省略
    • 函数体如果只有一句 return 语句,花括号也可以省略
    // 定义一个箭头函数
    let a = (arg)=>{ //  这里=>符号就相当于function关键字
        return arg+=1
    }
    // 也可以简写为
    let a = arg => arg+=1
    

    箭头函数也对 this 的指向做了修整

    es6 之前的函数的 this 指向调用函数时所在的对象,而箭头函数的 this 指向函数定义时所在的对象

    // 普通函数
     var obj = {
       say: function () {
         setTimeout(function() {
           console.log(this)
         });
       }
     }
    // 箭头函数
    var obj = {
        say: function () {
            setTimeout(() => {
                console.log(this)
            });
        }
    }
    obj.say(); // obj
    

    模板字符串

    模板字符串是为了解决使用+号拼接字符串的不便利而出现的。它的功能非常强大,但是我们大多数时候使用它则非常简单。

    // es6
    const a = 20;
    const b = 30;
    const string = `${a}+${b}=${a+b}`;
    
    // es5
    var a = 20;
    var b = 30;
    var string = a + "+" + b + "=" + (a + b);
    

    使用 `` 将整个字符串包裹起来,而在其中使用 ${} 来包裹一个变量或者一个表达式。

    class

    ES6 提供了更接近传统语言的写法,引入了 Class(类)这个概念,作为对象的模板。通过class关键字,可以定义类。

    先看如何定义一个class类:

    class User {
        constructor(name) {          // 构造器,相当于es5中的构造函数
            this.name = name         // 实例属性
        }
        showName(){                  // 定义类的方法,不能使用function关键字,不能使用逗号分隔
            console.log(this.name)   
        }
    }
    var foo = new User('foo')
    

    (1)constructor

    es6 中 class 类专用的构造器,相当于之前定义的构造函数,每个类都必须有constructor,如果没有则自动添加一个空的 constructor 构造器。
    创建实例的时候自动执行 constructor 函数
    constructor 中的 this 指向实例,并且默认返回 this(实例)

    (2)class 类的 prototype

    其实 class 的基本类型就是函数(typeof User = "function"),既然是函数,那么就会有 prototype 属性。

    类的所有方法都是定义在 prototype上

    class User {
      constructor() {
        // ...
      }
    
      toString() {
        // ...
      }
    
      toValue() {
        // ...
      }
    }
    User.toValue()             // err User.toValue is not a function
    User.prototype.toValue()   // 可以调用toValue方法
    
    // 等同于
    
    User.prototype = {
      constructor() {},
      toString() {},
      toValue() {},
    };
    

    (3)类的实例

    • 类的实例只能通过 new 来创建
    • 除了静态方法,定义在类上的所有的方法都会被实例继承
    • 除非定义在类的 this 对象上才是实例属性,否则都是定义在类的原型(prototype)上
    //定义类
    class Point {
    
      constructor(x, y) {
        this.x = x;
        this.y = y;
      }
    
      toString() {
        return '(' + this.x + ', ' + this.y + ')';
      }
    }
    
    var point = new Point(2, 3);
    
    point.toString() // (2, 3)
    
    point.hasOwnProperty('x') // true
    point.hasOwnProperty('y') // true
    point.hasOwnProperty('toString') // false
    point.__proto__.hasOwnProperty('toString') // true
    

    (4)静态方法

    如果在类中定义一个方法的前面加上 static 关键字,就表示定义一个静态方法,静态方法不会被实例继承,但会被子类继承,所以不能通过实例使用静态方法,而是通过类直接调用。

    class User {
        constructor(name){
            this.name = name
        }
        static show(){
            console.log('123')
        }
    }
    class VipUser extends User{}
    VipUser.show()                    // 123
    User.show()                       // 123
    var foo = new User('foo')
    foo.show()                        // foo.show is not a function
    

    (5)静态属性

    • class 的静态属性指的是 Class 本身的属性,目前只能通过 Class.propName 定义静态属性
    • 静态属性可以被子类继承,不会被实例继承
    class User{}
    User.name = 'foo' // 为class定义一个静态属性
    
    class VipUser extends User{}
    console.log(VipUser.name)         // foo
    
    var foo = new User()
    console.log(foo.name)             // undefined
    

    最后

    附赠一份【117页】前端面试题大全,内容包括:HTML相关、CSS相关、JavaScript相关、JQuery相关,数据请求相关,Vue相关、ES6相关,React相关、微信小程序相关,兼容性问题,浏览器适配问题 等等

    其中 ES6 相关面试题如下:

    ES6相关面试题

    • 列举常用的 ES6 特性:
    • 箭头函数需要注意哪些地方?
    • 箭头函数和普通函数之间的区别
    • let、const、var
    • var 方式定义的变量有什么样的 bug?
    • Set 数据结构
    • 数组去重的方法
    • 箭头函数 this 的指向
    • 手写ES6 class 继承
    • ES5 的继承和 ES6 的继承有什么区别?
    • ES6 class 的new 实例和ES5 的new 实例有什么区别?
    • generator 生成器函数
    • 什么是async/await 及其如何工作?
    • Promise 和async await 以及它们之间的区别:
    • async 函数的基本用法:
    • async 与 generator 的区别?
    • 简单实现 async/await 中的 async 函数
    • 有用过promise 吗?请写出下列代码的执行结果,并写出你的理解思路:
    • Object.is()与原来的比较操作符===,==的区别?
    • 介绍一下 Set、Map、WeakSet 和 WeakMap 的区别?
    • ES6 新特性详细介绍说明:
    需要【117页】前端面试题大全完整版(含解析)PDF文档的朋友 可以加入这边的Q裙:【624369675】,免费领取!
    

    相关文章

      网友评论

        本文标题:前端面试:ES6 基础知识点 & ES6 相关面试题

        本文链接:https://www.haomeiwen.com/subject/kbwyyltx.html