面试时面试官想要听到什么答案 关于es6中let、const、promise、块级作用域的问题

89500297 2020-01-10

前言

前面写了一篇关于vue方面问题的面试题(面试时面试官想要听到什么答案(关于一些vue的问题)),感谢大家的阅读和意见,今天整理了一下我面试时经常会问到的一些关于es的问题,写了这篇文章,感谢拨冗翻阅拙作,敬请斧正。
因为最近比较忙es6的问题就写了这些,写的比较水了,这些也是我比较常问的还有一些比较碎的内容面试问了但本文未体现只挑选了重点的,class和symbol也是两个重点,因为我了解不深所以就没有去问这两个 - -
下面进入正文,本文会列举一些平时面试时问到的问题和答案,并说明我在当时问到这个问题时所期望对方的回答:

es6有哪些属性

问题

常用的es6语法有哪些

问题描述

作为es6问题的开始的一个问题,想通过这个问题知道对方写代码时是否在用es6,是否知道自己用的是es6。但是大部分都说不上来几个(其实突然问我,我也不一定能说很多,当然面试多了之后就可以随口就来),所以我都怀疑这个问题有没有问的必要,对方这个问题其实回答的多少我后面还是该怎么问还是怎么问,也并不影响此次面试。

期望答案

let、const
解构赋值
模板字符串
箭头函数
函数默认值
promise
set、map结构
class类
symbol
Iterator 和 for…of 循环.
数值的扩展方法
数组的扩展方法
正则的扩展方法
对象的扩展方法
。。。。。。
以上为一些常用到的,还有一些不常用的就不一一列举了

var、let、const

问题

说下var、let、const的区别
问题描述
一个非常基础的问题,基本都是回答的差不多,不过有时候会说var和let的区别为一个没有作用域一个有作用域,显然这是一个误区。const是常量这个都知道,但是他可变的情况就很少有人清楚,阮一峰的《ECMAScript 6 入门》有详细的说明。

期望答案

let、const不存在变量提升,var存在变量提升
let、const不能重复声明,var可以重复声明
let、const有块级作用域,var没有块级作用域

补充:

块级作用域为 {} 只要被包裹在在{}中都是一个块级作用域,比如:if、for、function、或者是直接只写一个{}

const声明一个只读的常量。一旦声明,常量的值就不能改变。
本质: const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动。对于简单类型的数据(数值、字符串、布尔值),值就保存在变量指向的那个内存地址,因此等同于常量。但对于复合类型的数据(主要是对象和数组),变量指向的内存地址,保存的只是一个指向实际数据的指针,const只能保证这个指针是固定的(即总是指向另一个固定的地址),至于它指向的数据结构是不是可变的,就完全不能控制了。因此,将一个对象声明为常量必须非常小心。
所以const声明的对象、数组在对内部进行操作时是并不会报错的,即const声明的可变情况。

块级作用域和函数声明

问题

块级作用域对函数声明有什么影响或改变
问题描述
这个问题我并没有在面试中问过,因为这个问题其实很抽象而且很难去说明,而且这个环境问题就很难去模拟,下面是我在查阅了一些文档和书之后的一些理解,如果有问题,敬请斧正。
阮一峰的《ECMAScript 6 入门》中let、const中有一节是对这一块的描述。

期望答案

ES5 规定,函数只能在顶层作用域和函数作用域之中声明,不能在块级作用域声明。但是,浏览器没有遵守这个规定,为了兼容以前的旧代码,还是支持在块级作用域之中声明函数,不会报错。
ES5环境下可以实现下面代码

demo()  // 打印 bbb
var flag = true
if (flag) {
    function demo() {
        console.log(‘aaa‘)
    }
} else {
    function demo() {
        console.log(‘bbb‘)
    }
}

执行此代码时,会先将函数声明提升到顶部而并不会根据判断在下面进行声明,打印bbb是因为第一个声明被第二个声明覆盖了(《你不知道的javaScript》第一部分第四章第三节),实际为下面代码:

function demo() {
    console.log(‘aaa‘)
}
function demo() {
    console.log(‘bbb‘)
}
var flag
demo()  // 打印 bbb
flag = true
if (flag) {
} else {
}

ES6 引入了块级作用域,明确允许在块级作用域之中声明函数。ES6规定,块级作用域之中,函数声明语句的行为类似于let,在块级作用域之外不可引用。
如果改变了块级作用域内声明的函数的处理规则,显然会对老代码产生很大影响。为了减轻因此产生的不兼容问题,ES6 在附录 B里面规定,浏览器的实现可以不遵守上面的规定,有自己的行为方式。

允许在块级作用域内声明函数。
函数声明类似于var,即会提升到全局作用域或函数作用域的头部。
同时,函数声明还会提升到所在的块级作用域的头部。

注意,上面三条规则只对 ES6 的浏览器实现有效,其他环境的实现不用遵守,还是将块级作用域的函数声明当作let处理。
上面代码的执行顺序会变为

var flag
var demo
demo()  // demo is not a function
flag = true
if (flag) {
    function demo() {
        console.log(‘aaa‘)
    }
} else {
    function demo() {
        console.log(‘bbb‘)
    }
}

promise

问题

一般情况这个问题我会给面试者出一个代码题

console.log(1)
let promise = new Promise((resolve, reject) => {
    console.log(2)
    resolve()
    console.log(3)
})
setTimeout(() => {
    console.log(4)
}, 0);
console.log(5)
promise.then(() => {
    console.log(6)
})
console.log(7)

问题描述

正确执行顺序我会放在期望答案的最后,防止在看题时看到结果。
这个问题主要问的是两个关键点:1. promise在构造时内部就已经执行结束。2. promise.then和setTimeout的执行顺序

期望答案

关键点1:在Promise对象new的时候,Promise内部resolve前后就都执行了,resolve只与then有关(resolve调用时的参数为then的参数),并不会阻止后面代码的执行。
关键点2:promise.then的执行时间会早于setTimeout,promise和setTimeout都可以处理异步问题,promise为微任务setTimeout为宏任务,promise.then会在本次任务的最后的去调用,而setTimeout会开启一个新的任务去执行其内部的内容,即下一次任务的开始。所以6比4先打印。

问题执行结果:1 2 3 5 7 6 4

 

相关推荐