ES6 面试常考题库【3】

第三篇


一些常见的面试题内容,希望也能助你一臂之力🌸🌸🌸🌸🌸

Q1、ES6新增的set集合是什么?

ES6提供新的数据结构,类似于数组,但成员的值都是唯一的
集合实现了iterator接口,可以使用扩展运算符和for .. of进行遍历
// 常使用API
 // 声明一个set集合
  let s = new Set();

   // 自动去重
   let s1 = new Set(['大事情','小事情','大事情','坏事情','好事情'])
   // 元素个数
   console.log(s1.size); //4

   // 添加新的元素
   s1.add('开心')

   // 删除元素
   s1.delete('坏事情')

   // 检测
   console.log(s1.has("开心")) // true

   // 使用for of遍历
   for(let v of s1){
       console.log(v) //大事情 小事情 好事情 开心
   }
   //清空
   s1.clear();
   console.log(s1); // Set(0) {size: 0}
// 举个例子
// 声明两个数组
    let arr1 = [1,3,2,3,4,7,8,4,2,3,9];
    let arr2 = [2,3,7,5,7,5,4,1];

    // 1、数组去重
    let result1 = [...new Set(arr1)]; //使用扩展运算符
    console.log(result1); //(7) [1, 3, 2, 4, 7, 8, 9]

    // 2、求交集
    // 扩展运算符将每一项展开 过滤写法
    // let result2 = [...new Set(arr1)].filter(item=>{
    //     let s2 = new Set(arr2);
    //     if(s2.has(item)){
    //         return true;
    //     }else{
    //         return false;
    //     }
    // })
    //简写
    let result2 = [...new Set(arr1)].filter(item => new Set(arr2).has(item))
    console.log(result2); //(5) [1, 3, 2, 4, 7]

    //3、求并集
    let union = [...arr1,...arr2];
    let result3 = new Set(union)
    console.log(result3); //Set(8) {1, 3, 2, 4, 7, …}

    // 4、求差集
    let result4 = [...new Set(arr1)].filter(item=>!(new Set(arr2).has(item)))
    console.log(result4); //(2) [8, 9]

Q2、什么是map?

ES6提供的新数据结构,类似于对象,也是键值对的集合。”键值“不限于字符串,也可以是各类型的值(对象)。
map实现了iterator接口,可以使用扩展运算符 和  for...of 进行遍历
相关属性和方法:
	size、setget 、has、 clear
// 举个例子
	// 声明map
   let m = new Map();
    // 添加元素
    m.set('name','小天');
    m.set('change',function(){
        console.log("学习前端开发!")
    })
    let key = {
        school:'ATGUIGU'
    }
    m.set(key,['北京','上海','天津'])

    // 获取长度
    console.log(m.size) //3

    // 获取属性值
    console.log(m.get('change')) // f(){ console.log("学习前端开发!") }

	// 是否存在某个属性
    console.log(m.has('name')) //true

    // 删除
    m.delete('name')

    // 清除
   m.clear();

Q3、Class 的基本语法

实例化对象
		// ES5实例化一个对象
        function Phone(brand,price){
            this.brand = brand,
            this.price = price
        }
        // 添加方法
        Phone.prototype.call = function(){
            console.log("打电话的手机!")
        }
        // 实例化对象
        let HuaWei = new Phone('华为I8',8555);
        console.log(HuaWei); // Phone {brand: '华为I8', price: 8555}

        // ES6 使用class 实例化对象
        class Shouji{
            // 构造方法,名字不能修改
            constructor(brand,price){
                this.brand = brand,
                this.price = price
            }
            // 添加方法
            call(){
                console.log("发短信的手机!")
            }
        }
        let onePlus = new Shouji("1+",1200);
        console.log(onePlus); // Shouji {brand: '1+', price: 1200}

// ES6的类
1、类的数据类型就是函数,类本身就指向构造函数。
   使用的时候,也是直接对类使用new命令,跟构造函数的用法完全一致
    class Point{
        say(){
            console.log('hello class');
        }
      }
      console.log(typeof Point) // function
      console.log(Point === Point.prototype.constructor) //true

    //  使用new 关键字实例化一个类
      const p = new Point();
      p.say(); // hello class

// 表达式的形式定义类
// 这个类的名字是Me,但是Me只在 Class 的内部可用,指代当前类。
// 在 Class 外部,这个类只能用MyClass引用
const MyClass = class Me {
  getClassName() {
    return Me.name; //内部使用
  }
};
let my = new MyClass();
my.getClassName() // Me
// Me.name // ReferenceError: Me is not defined

静态成员 
   // 静态属性属于类(构造函数对象身上的属性可以获取得到),但是实例自身上不能获取得到
   class Phone{
       // 静态属性
       static name = '手机';
       // 静态方法
       static change(){
           console.log("摔不坏")
       }
   }
   let nokia = new Phone();
   console.log(nokia.name); //实例       undefined
   console.log(Phone.name); //函数对象身上  手机

Q4、Class 的继承

ES5的继承:让子级原型,成为父级的实例上的一个实例对象
	// ES5实现继承
      function Phone(brand,price){
         this.brand = brand;
         this.price = price;
     }
     Phone.prototype.call = function(){
         console.log("我是父级身上的方法")
     }
     function Shouji(brand,price,color,size){
             Phone.call(this,brand,price);
             this.color = color;
             this.size = size
         }
     //设置子级原型,成为父级的实例上的一个实例对象
     Shouji.prototype = new Phone;

     // 修改子级上的构造函数指向
     Shouji.prototype.constructor = Shouji;

     // 声明子类的方法
     Shouji.prototype.play = function(){
         console.log("我是子级身上的方法")
     }
     let parrent = new Phone("华为",8000); //父类的实例
     let children = new Shouji('I8系列',2000,'black','4.5inch'); //子类实例
     
     children.play(); //子类调用自身上的方法
     children.call(); // 子类调用父级身上的方法

// ES6实现继承
   class Phone{
        constructor(brand,price){
            this.brand = brand;
            this.price = price
        }
        // 方法
        call(){
            console.log("打电话!")
        }
    }
    // 子类
    class SmartPhone extends Phone{
        // 构造方法
        constructor(brand,price,color,size){
            super(brand,price); //Phone.call(this,brand,price);
            this.color = color;
            this.price = price
        }
        photo(){
            console.log('我是子类自生上是方法')
        }
        // 我是子类对父类方法的重写 ES5不可以
        call(){
            console.log('我是子类对父类方法的重写')
        }
    }
    const xiaomi = new SmartPhone('小米',799,'white','4.7inch')
    xiaomi.photo(); // 子类自生上的方法
    xiaomi.call();  // 子类对父类方法的继承

Q5、ES6新增加的数值扩展有哪些?

// (1)Number.isFinite //检测一个数值是否为有限数
     console.log(Number.isFinite(15)) //true
     console.log(Number.isFinite(0.8)) //true
     console.log(Number.isFinite(Infinity)) //false
     console.log(Number.isFinite('15')) //false
     console.log(Number.isFinite(true)) //false

     // (2) Number.isNaN   //判断是否为NAN
     console.log(Number.isNaN(NaN)) //true
     console.log(Number.isNaN(15))  //false

     // (3)Number.parseInt  // (4)Number.parseFloat
     // 将全局方法parseInt()和parseFloat(),移植到Number对象上面
     //ES5写法
     console.log(parseInt('3.14259')) //3
     console.log(parseFloat('3.14Π')) // 3.14
     //ES6写法
     console.log(Number.parseInt('3.14159')) //3
     console.log(Number.parseFloat('3.14Π')) // 3.14
     
     // (5)Number.isInteger    //是否为整数
     console.log(Number.isInteger(25) ) // true
    console.log( Number.isInteger(25.1)) // false

     // (6)Math.tunrc   //用于去除一个数的小数部分,返回整数部分
     console.log(Math.trunc(4.1)) //4
     console.log(Math.trunc(4.9)) //4
     console.log(Math.trunc(-4.1)) //-4
     console.log(Math.trunc(-4.9)) //-4

Q6、ES6模块化是什么?

ES6 模块的设计思想是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。
CommonJS(输入时必须查找对象属性) 和 AMD 模块,都只能在运行时确定这些东西。
模块化优点是:防止命名冲突、代码复用、高维护性
// CommonJS模块
let { stat, exists, readfile } = require('fs');

// ES6模块
import { stat, exists, readFile } from 'fs';
模块功能主要由两个命令构成:exportimportexport命令用于规定模块的对外接口,import命令用于输入其他模块提供的功能。
一个模块就是一个独立的文件。该文件内部的所有变量,外部无法获取。
外部能够读取模块内部的某个变量,就必须使用export关键字输出该变量。
对外暴露方式:
	//分别暴露
     export let school = {
         name:'大前端'
     }
     export function fun(){
         console.log('学习ES6')
     }

     //统一暴露
     let school = 'W3C'
     function fun(){
         console.log('第二种暴露方式')
     }
     export {school,fun};

     //默认暴露
     export default{
         school:'W3CSchool',
         change:function(){
             console.log('第三种暴露方式')
         }
     }
      // 使用默认暴露中的方法
     m1.default.change();
模块引入方式:
	//模块化引入(第一种)
        // 通用的导入方式
        // 引入m1.js
        // import * as m1 from './m1.js';

        // 解构赋值的形式
        // 对分别暴露
        // import {school,fun} from './m1.js';
         // 对统一暴露 同名的可以重名
        //import {school as scl,fun} from './m1.js'
        //对默认暴露方式
        // import {default as m1 } from './m1.js'
        
        // 简便形式 默认暴露
        // import m1 from './m1.js'

    // 模块化引入(第二种)
        // 入口文件
        // 模块引入
        import * as m1 from './m1.js';
        // src 引入
        <script src="./app.js" type="module"></script>

Q7、为什么引入 async 函数以及其作用?

async 函数 使得异步操作变得更加方便,它就是 Generator 函数的语法糖(使用语法糖能够增加程序的可读性,从而减少程序代码出错的机会)
// 举个例子
 //Generator 函数,依次读取两个文件
 const fs = require('fs');

const readFile = function (fileName) {
  return new Promise(function (resolve, reject) {
    fs.readFile(fileName, function(error, data) {
      if (error) return reject(error);
      resolve(data);
    });
  });
};
const gen = function* () {
  const f1 = yield readFile('/etc/fstab');
  const f2 = yield readFile('/etc/shells');
  console.log(f1.toString());
  console.log(f2.toString());
};

// async 函数,依次读取两个文件
const asyncReadFile = async function () {
  const f1 = await readFile('/etc/fstab');
  const f2 = await readFile('/etc/shells');
  console.log(f1.toString());
  console.log(f2.toString());
};

Q8、async函数的改进体现在哪些方面?【By:ES6阮一峰】

(1)内置执行器:asyncReadFile(); 调用该函数,代码自动执行,输出最后结果
		Generator 函数,需要调用next方法,或者用co模块,才能继续往下执行。
(2)语义更加明了
		async和await,比起 * 和 yield,语义更清楚了。
		async表示函数里有异步操作,await表示紧跟在后面的表达式需要等待结果
(3)使用范围广
		co模块约定,yield命令后面只能是 Thunk 函数或 Promise 对象。
		而async函数的await命令后面,可以是 Promise 对象和原始类型的值(数值、字符串和布尔值,但这时会自动转成立即 resolved 的 Promise 对象)
(4)返回值是 Promise。
		async函数的返回值是 Promise 对象,这比 Generator 函数的返回值是 Iterator 对象方便多了。
		可以用then方法指定下一步的操作

async函数的基本使用

async函数返回一个 Promise 对象,可以使用then方法添加回调函数。
当函数执行的时候,一旦遇到await就会先返回,等到异步操作完成,再接着执行函数体内后面的语句
// 函数声明
async function foo() {}

// 函数表达式
const foo = async function () {};

// 对象的方法
let obj = { async foo() {} };
obj.foo().then(...)

// Class 的方法
class Storage {
  constructor() {
    this.cachePromise = caches.open('avatars');
  }

  async getAvatar(name) {
    const cache = await this.cachePromise;
    return cache.match(`/avatars/${name}.jpg`);
  }
}

const storage = new Storage();
storage.getAvatar('jake').then();

// 箭头函数
const foo = async () => {};

Q9、await命令

1、await必须写在async函数中
2、await右侧的表达式一般为promise对象,如果不是 Promise 对象,就直接返回对应的值。
3、await语句后面的 Promise 对象变为reject状态,那么整个async函数都会中断执行。
如果希望await后 Promise 对象变为reject,但不中断后面的异步操作。
可以将第一个await放在try...catch结构里面,这样不管这个异步操作是否成功,第二个await都会执行。
// 举个例子
// 第一种
  async function mian(){
       try {
           await Promise.reject('出错了!')
       } catch (error) {
           return await Promise.resolve('不影响后续执行')
       }
    }
    mian().then(
       v => console.log(v)
    )
   // 结果: 不影响后续执行

// await后面的 Promise 对象再跟一个catch方法,处理前面可能出现的错误。
   //  第二种
   async function Main(){
       await Promise.reject('出错了!').catch(
           e => console.log(e)   //处理肯出现的错误
       )
       return await Promise.resolve('不影响后续执行')
   }
   Main().then(
       v => console.log(v)
   )
   // 结果:出错了!  
   //      不影响后续执行

Q10、async函数的执行原理?

将 Generator 函数和自动执行器,包装在一个函数里。
// 举个例子
async function fun(args) {
  // ...
}

// 等同于

function fun(args) {
  return spawn(function* () {  // spawn函数就是自动执行器
    // ...
  });
}

休息一下,下一篇下一篇

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值