前端面试题 我在面试bat字节时被问的ES6相关问题_前端小黑的博客-程序员秘密

技术标签: ES6学习笔记  面试题  

做为前端开发,应该都知道,ES6是我们必学的,而之所以强调ES6,是因为在ES6那个版本增加了很多东西,以至于阮一峰大佬还写了本书,也因此,我们经常会在面试里面被问到,你了解ES6吗,知道哪些新特性,而在你说出来之后,就会引来一系列的问题,这篇博客就从我面试bat字节时被问到的一些问题和网上的面经结合做一些总结和问题的回答,同时也会谈到如何从被问的问题里面“引导”面试官去问你其他的问题

新增声明符let const


我们知道,在ES6里面,多了两个声明符,let和const,如果你提到了这个,那么可能会面临下面的问题

var let const三者的区别

作用域的区别

var声明的变量可以在全局作用域,函数作用域和严格模式下的eval作用域里使用,而let和const多了个块级作用域,在if、else、while、for循环的{}里声明的变量,无法在该{}外部使用(这里提到作用域也许会让面试官问到作用域嵌套,当然你也可以自己刻意提起,比如可以说在函数作用域里声明的变量,虽然是被嵌套在另一个函数作用域或者全局作用域里面,但无法使用这个变量,而相对的在函数作用域里面可以使用嵌套它的作用域里声明的变量)

变量提升

var声明的变量有变量提升的特点,在声明一个变量时变量会被提升到文件顶部,所以我们可以使用后面var声明的变量,但是此时变量的值为undefined,而let和const,因为没有变量提升,所以如果在声明前使用的话会引起报错

变量是否可变

这个是关于const声明的变量的特性,是面试中经常被问到的(反正我在面腾讯百度字节都被问到了),const声明的变量不能被重新赋值,如果重新赋值,就会报错,提到这个问题时,就会引出下面的问题

  • const声明的对象,对象的属性可以改变吗:可以,const声明的对象,不能重新赋值,但其对象的属性是可以变化的,我的理解是,const声明的变量不能改变,是指这个变量指向内存中哪一段内容不能变,而对于对象来说,我们的变量存储的是一个地址,表示对象在内存中,在堆中所处的位置,而对象的属性改变,并不会改变这个指向
  • 如何让声明的对象的属性也不能被改变:我自己想到的方法有:proxy代理,Object.defineProperty劫持set操作,Object.freeze,可能还有别的方法,但我当时只回答了这些

箭头函数


箭头函数在ES6时被提出,现在也被广泛运用到开发中,但如果没有好好地去了解它,那么开发时也可能会踩到莫名其妙的坑

箭头函数和一般函数的区别

this指向

箭头函数的this,指向了其执行时所在的作用域,而一般函数的this指向,要考虑到是否用到new构造,是否用到了apply,call,bind来进行this的指向修改

  • 问到了这个问题,一般就会问到了apply,call,bind的区别了,包括this的四种指向的情况,这个可以在《你不知道的JavaScript》里面看,我觉得挺详细的,当然网上也有很多介绍详细的文章了,这里不做赘述

不能使用apply,call,bind

这个也是上面提到的了,因为箭头函数的this是其执行时所在的作用域,所以也无法同个apply,call,bind来改变this指向

  • 这里说一下,你可以直接在这里顺便说一下apply,call,bind三者的区别,让面试官知道你这方面也是了解的,而此外,你也可以提提这三者哪个的性能比较好,这个我也做过了测试,所以在面试的时候我也会说出来,自己测试过这三个的性能,哪个比较好,感觉会留下比较好的印象,至少你有去多做考虑,而不是只会用,详见我之前写的博客JavaScript辨别apply,call,bind 用法与性能

无法使用arguments对象

一般的函数如果我们传入的参数个数是不定的话,那么可以通过arguments对象来列出所有传入的参数,而箭头函数却不能使用这个对象,但是,我们可以使用扩展运算符来代替arguments对象

不能使用yield命令

箭头函数不能使用yield命令,因此箭头函数不能使用generator函数(这个回答的话可以考虑是否回答,如果你对generator函数并不是很了解,那就可以不说,不然面试官可能会问你相关的知识,别问我为什么知道的。。。)

没有prototype属性,无法通过new来构建实例

箭头函数没有prototype属性,而我们知道,new构建实例时除了需要对this的指向进行指定,还要让实例对象继承该方法的原型,所以箭头函数也就无法使用new来构建实例

箭头函数的优点

要说箭头函数的优点,我也没有准确的答案,我就发表一下我个人的观点

  • 写的时候比较比较便利,虽说function这个单词也不难写,但是显然,直接用()=>{}的写法会更快
  • 相对代码体积比较小,在很小的程度上有一点性能的提高
    (实际上这点提高可能在写的函数特别多的时候会有感觉,但一般我其实觉得还是没什么大影响,而且虽说现在浏览器大多支持箭头函数语法,但是我们在写的时候一般还是会通过babel进行一个编译,所以实际上这个优点有点牵强,但是只说一点又好像不太好,总之这种问题就是言之有理即可,尽量让面试官觉得你有好好地思考,逻辑合理就行)

什么时候适合使用箭头函数

这个也是一种挺开放的问题了,主要把适合用的原因说清楚就行

  • 首先,肯定是在不需要去实例化,改变this指向时使用,只要不是使用箭头函数会影响到实际功能的,就可以出于编码便利的理由去使用箭头函数
  • 还有就是,在我们要用到的this,确实就是指向所在作用域的时候,当然这种情况比较少见,而且会对代码的语义有一点影响,最好不要在多人参与的项目里面这么用

Map与Set


这两个倒是比较少问到,虽然我每次面试被问到ES6了解哪些时都有提到,但只有面试百度的时候被问到了,姑且写一下
(关于Map和Set,可以直接看阮一峰的ES6入门,也可以看看我看了这本书做的笔记ES6学习笔记(五)Set结构和Map结构

Map和Set怎么使用,特点是什么

当时我回答的时候,就回答了Map和Set里面的结构是什么,比如Map传入的数组参数,是一个二元数组,每个数组成员里面有两个成员,第一个值为键名,第二个值为键值

new Map([[k1,1],[k2,2]]);

包括用到的一些API,其实也就get,set那些,忘了的话也没太大关系(emmmmm反正那次百度面试我是过了)
然后Set的话也差不多,但是Set我倒是在做算法题时有时会直接用来做去重处理,面试的时候也就顺便提了一下,结果面试官可能觉得我Set比较熟,就继续问下去了。。。

Set传入的值如果在这个Set中已经有该值了,那会发生什么

如果Set中已经有该值了,那么继续添加的话会静默失败

  • 如果添加进去的,是一个属性相同的对象呢:如果这个对象是存储在这个变量的话,如下(当时是视频面试,所以可以写代码给面试官看)
var obj = {
    foo:1}
var s = new Set([obj])
s.add(obj)

那还是会静默失败,但是如果添加的是一个没有存储在变量里的对象,也就是说,每次都是在堆内存里新开辟一部分内存,然后将指向那部分内容的地址存入Set里面,那么因为每次地址都不同,所以每次都会存入成功,就像下面的代码

var s = new Set([{
    foo:1}])
s.add({
    foo:1})

所以这里其实还是需要对对象的存储方式有所了解,这也是比较基础的内容,要好好打牢(顺便一提关于基本类型和引用类型的存储方式在几个大厂除了bat字节外包括京东网易也都被问过了)

Promise


promise异步相信也是经常在面试题里见到了,包括笔试题也是,那些打印顺序什么的,这里就说说我被问到的一些问题

Promise.then

首先要知道,promise.then是一个微任务,想到了微任务,你可能就会想到面试笔试里出现的这类题目
(下题为我面试字节时的真题)

console.log('begin');
setTimeout(() => {
    
    console.log('setTimeout 1');
    Promise.resolve().then(() => {
    
        console.log('promise 1');
        setTimeout(() => {
    
            console.log('setTimeout2 between promise1&2');
        })
    }).then(() => {
    
        console.log('promise 2');
    });
}, 0); console.log('end');

提问:上面的打印顺序是什么,其实这主要是微任务和宏任务的问题,除了单方面回答这道问题的答案外,还可以顺便说一下除了setTimeout和Promise.then外,还有什么宏任务,微任务(关于这个,我之前也有相关的文章:详解JavaScript异步执行顺序

Promise.all是怎么实现的

这个可能就是考考你对promise一些API的了解,其实也就是,传入一个数组,数组里面所有的成员,如果不是promise对象的话,就先使用Promise.resolve处理,接着,如果里面所有的Promise状态都变成resolved的话,那么这个方法返回的Promise的状态就变成resolved,而只要里面一个状态变成rejected,返回的Promise的状态就为rejected
接着,我就手写了Promise.all。。。,还好之前自己写过

Promise._all = function(promises){
    
    return new Promise((resolve,reject)=>{
    
        // 将可遍历的类型转为数组形式
        promises = Array.from(promises)
        // 若数组长度为0,则直接resolve([])
        if(promises.length === 0){
    
            resolve([])
        }else{
    
            // 使用一个变量count来计算当前已完成的promise
            let count = 0
            for(let i=0;i<promises.length;i++){
    
                Promise.resolve(promises[i]).then(val=>{
    
                    promises[i] = val
                    // 若完成的promise数量和数组长度一致,说明全部完成,则返回处理好的数组
                    if(++count === promises.length){
    
                        resolve([promises])
                    }
                }).catch(err=>{
    
                    reject(err)
                })
            }
        }
    })
}

顺手贴上我自己写的Promise.race的实现代码

Promise._race = function(promises){
    
    promises = Array.from(promises)
    return new Promise((resolve,reject)=>{
    
        promises.forEach(p=>{
    
            Promise.resolve(p).then(val=>{
    
                resolve(val)
            }).catch(err=>{
    
                reject(err)
            })
        })
    })
}

比起使用回调,使用Promise的好处

  • 首先,使用回调可能会造成回调地狱,而使用Promise,以then的方式,不仅避免了回调地狱,还使代码的可阅读性更高
  • 其次使用Promise可以更好地实现异步,说到底,Promise就是一个异步方法
  • 还有,使用Promise实现异步的时候,可以通过将状态变更方法赋值给Promise外的变量,让我们能在Promise外部进行异步的处理,这点在axios的源码里面就有运用到(因为我自己看过axios的源码,本来想引导看面试官会不会问到axios的源码上,结果没问)

我在面试时被问到的暂时就是这些,还有其他的内容我会在之后慢慢补充进这篇博客

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/zemprogram/article/details/105926769

智能推荐

uniapp之Web-view遮挡导航方案_小熊代码加的博客-程序员秘密

方案一:pages.json定义原生导航{ "path": "pages/checkout/checkout", "style": { "app-plus": { "navigationBarTitleText": "个人中心", "titleNView": { "autoBackButton": false,

spark性能优化点(1)_wang987158的博客-程序员秘密

1. 分配更多的资源1.1 分配哪些资源1.2 在哪里可以设置这些资源1.3 参数调节到多大,算是最大分配更多的资源:它是性能优化调优的王道,就是增加和分配更多的资源,这对于性能和速度上的提升是显而易见的,基本上,在一定范围之内,增加资源与性能的提升,是成正比的;写完了一个复杂的spark作业之后,进行...

对辛辛那提原始数据集(ims)数据划分正常,内圈故障,滚动体故障,外圈故障(python代码),可作为自己故障诊断模型实验的另一个数据集(因为CWRU普遍而言,准确度和被使用频率已经极高)_ims数据集_深度学习的奋斗者的博客-程序员秘密

1.IMS数据集一般用来做设备可用寿命预测,但是,在故障分类领域,越来越多的人也在使用 原始数据下载官网(https://ti.arc.nasa.gov/tech/dash/groups/pcoe/prognostic-data-repository/#bearing)2.说明一下正常样本,内圈故障样本,外圈故障样本,滚动体故障样本的取文件范围: 在提取时,包含原始数据的压缩文件提供了三个文件夹:1st_test、2nd_test和3rd_test以及一个文档文件。在3...

Java服务导致CPU飙100%的问题解决_尤尤尤奴斯的博客-程序员秘密

生产环境一直会规律性出现CPU冲高的问题,回顾一下解决过程。首先定位到进程:以下命令二选一top#或者使用组合命令ps aux|head -1ps aux|grep -v PID|sort -rn -k +3|head可以确定cpu使用率高是JVM引起的。查看最近一段时间的JVM内存和GC的监控信息如果有zabbix等监控辅助你定位问题那是最好的,如果没有监控可以使用命令:jstat -gcutil PID 查看JVM的GC信息和内存使用信息jstat -gcutil 6124

宝塔linux请先安装mysql数据库_宝塔服务器管理助手Linux版详细安装教程_欢乐马欢的博客-程序员秘密

宝塔服务器管理助手提供了包括Windows和Linux系统平台下的服务器管理面板,免费使用,安装方便,界面直观。Linux版本支持CentOS6.x和7.x系统,安装的软件包括Nginx-Tengine、Nginx、Apache、PHP、MySQL、FTP和PHPMyadmin数据库管理等。本篇讲述的是Linux版的安装教程,Windows版本的可直接在服务器上下载,或者上传程序至服务器,进行视图...

python源码精要(9)-CPython内部原理快速指南(1)_python x.py doc library/std_水木森的博客-程序员秘密

对于那些有兴趣了解更多关于CPython内部原理的人,这是一个快速指南。它提供了一个摘要的源代码结构,并包含对资源的引用。对于Python模块,典型的布局是:• Lib/&lt;module&gt;.py• Modules/_&lt;module&gt;.c (if there’s also a C accelerator module)• Lib/test/test_&lt;module&gt;.py• Doc/library/&lt;module&gt;.rst对于只支持扩展的模块,典.

随便推点

cfnet用于嵌入式_做嵌入式驱动的,你一定要挺住!_weixin_39653311的博客-程序员秘密

搞嵌入式驱动开发一年多了,项目做的不少:从网络驱动到CAN驱动、从Dataflash驱动到NAND/NOR FLASH驱动、从CF/IDE驱动到各种嵌入式文件系统、从LCD/VGA驱动到音频驱动、从IAR到ADS再到GCC、Ucos到linux、从I2C总线到SPI再到SSC以及TCP/IP协议。但感觉并没有学到什么东西,除了一个字:累!老实说这些项目,很少有驱动是自己动手写的,基本都是找来相近的...

无法启动代理。 (查看快照代理状态)执行 Transact-SQL 语句或批处理时发生了异常。 (Microsoft.SqlServer.ConnectionInfo)_橙-极纪元的博客-程序员秘密

===================================无法启动代理。 (查看快照代理状态)------------------------------有关帮助信息,请单击: http://go.microsoft.com/fwlink?ProdName=Microsoft%20SQL%20Server&amp;ProdVer=12.0.2000.8&amp;EvtSr...

用jQuery的attr()方法设置属性值无效怎么办?_kingbow。的博客-程序员秘密

无疑的jquery是一个极其强大的前端框架,作为一名前端程序员,jQuery几乎是其必备技能,然而有时候却出现jquery失效的情况,现在我们就来讨论为何用jquery的attr方法会失效。我有些CheckBox类型的html控件,通过一个按钮来使用jquery的attr方法来控制选中或者取消选中。奇葩的事情发生了,我第一次选中成功,第一次取消选中也成功,然后我再次进行选中,,,失败了!...

C++/MFC 面试题(三、C++11与STL)_LyRics1996的博客-程序员秘密

一、STL标准模板库(Standard Template Library)包含了很多实用的组件,利用这些组件,程序员编程更加方便高效1.1 STL的基本组成部分是什么?容器、迭代器、算法是STL的三个基本组成部分容器:是对象的集合,举例:vector、list、stack、queue、set、map、deque迭代器:面向对象版本的指针,STL算法通过迭代器在容器上进行操作算法:对容器进程处理的函数,如:for_each、copy、sort、merge、search1.2 vector容器与

SqlServer 使用Navicat 设置主键自增问题_滨海之君的博客-程序员秘密

由于Navicat不支持sqlserver的主键自增设置,需要自己写sql设置:alter table 表名 add 主键字段名 int identity(1,1) primary key(主键字段名

【转】ASP.NET ViewState详解_agnsm00804的博客-程序员秘密

(wyt今天学习了这篇文章,作为门外汉的我了解了很多页面控件数据加载的知识和viewstate的用法和原理。我想在日后的开发效率提升上会有很大的作用。)转自http://www.cnblogs.com/wwan/archive/2010/11/18/1880357.html概述ViewState是一个被误解很深的动物了。我希望通过此文章来澄清人们对ViewSta...

推荐文章

热门文章

相关标签