es6面试题

1. 请说出下列最终执行结果,并解释为什么?

var a = [];
for(var i = 0; i < 10; i++) {
 a[i] = function() {
   console.log(i)
}
}
a[6]()

 

输出10

var没有块级作用域,声明的变量直接到全局

当for循环执行完成时候,全局i已经为不满足条件的10,

执行函数时候,先查找函数内部有没有i变量,找不到之后通过作用域链直接查找到全局

此时全局的i已经为10,所以输出10 

2. 请说出此案列最终执行结果,并解释为什么?

var tmp = 123;
if (true) {
 console.log(tmp);
 let tmp;
}

报错:Uncaught ReferenceError: Cannot access 'tmp' before initialization

let声明的变量会在当前块级作用域形成暂时性死区,不会查找到全局

let的变量只能先声明再使用,所以报错

 

3. 结合ES6语法,用最简单的方式找出数组中的最小值

var arr = [12, 34, 32, 89, 4]
Math.max(...arr)

 

 

4. 请详细说明var、let、const三种声明变量的方式之间的具体差别

 

var:

  1. 变量提升

  2. 全局声明的变量会挂载到window上

  3. 没有块级作用域

let:

  1. 没有变量提升

  2. 具有块级作用域

  3. 块内部定义的变量会形成暂时性死区

  4. 变量只能先声明再使用

const:

  1. 变量定义以后不允许修改他的引用地址,基础类型不能修改

  2. 其他特性跟let一致

5. 请说出下列代码最终输出结果,并解释为什么?

var a = 10;
var obj = {
 a: 20,
 fn() {
   setTimeout(() => {
     console.log(this.a)
  })
}
}
obj.fn()

 

输出20

箭头函数的this跟定义箭头函数的上下文this绑定

所以定时器回调内部this绑定成fn内部的this

fn是通过obj调用,所以fn内部this指向obj

即最终定时器回调内部this.a ==> obj.a ==> 20

6. 简述Symbol类型的用途

用于创建独一无二的值,可做唯一key用于缓存等场景 用于创建类的私有变量,利用symbol属性不能被枚举的特性声明作为私有属性 用来重置对象的属性,比如 Symbol.toStringTag 可实现 Symbol.iterator迭代器, 让普通对象变为可迭代对象 使用Symbol.for('xxx')获取全局的symbol值

 

7. 说说什么是浅拷贝,什么是深拷贝?

  1. 浅拷贝对于引用类型来说,只拷贝了引用地址,所以复制后的对象修改了可能会影响原对象

  2. 深拷贝,完全拷贝引用类型的数据结构

 

浅拷贝示例:下面这个复制,栈当中只存储了对象在堆内存的引用地址,如果直接复制给b,拷贝的只是一个地址,地址指向的还是同一个堆空间,所以本质上a和b是同一个对象

const a = {
 name: '拉勾教育',
}

const b = a;

 image-20210423233317643

深拷贝原理:开辟一个新的内存空间,存储空对象(与源对象无关),然后递归遍历源对象结构(直到源对象都为基本数据类型),然后进行给空对象的复制操作

8. 请简述TypeScript与JavaScript之间的关系?

 

  1. 官方定义:ts为js的超集

  2. 解决了js语言自由的类型系统的不足,提高了代码的严谨程度,js类型系统不足的终极解决方案

  3. 最终还会编译成js执行

9. 请谈谈你所认为的typescript优缺点

 

  1. 优点:对于大型项目,限制了很多类型上面会出现的bug,提升了项目的严谨性可靠性,提升开发效率

  2. 缺点:对于小型项目,一开始构建类型限制反而会增加工作量

    总结:对于大型项目,可能只是一开始增加点类型配置工作量,对于长远来看,一劳永逸

10. 描述引用计数的工作原理和优缺点

 

  1. 原理: 设置引用计数,判断当前引用数是否为0,引用关系改变时修改数字(对象引用计数的数值来决定垃圾回收时机,如果为0,则回收) 

  2. 优点:

    1. 发现垃圾立即回收

    2. 最大程度减少程序暂停

  3. 缺点:

    1. 无法回收循环引用对象

11. 描述标记整理算法的工作流程

 标记清除的增强版

  1. 从根节点,找能够标记的对象

  2. 清除阶段会执行整理,移动对象的位置,让可回收对象的内存连起来(解决标记清除内存碎片化问题)

  3. 最后清除需要回收的对象,释放内存,供程序使用

 

12.描述V8中新生代存储区垃圾回收的流程

  1. v8 对于垃圾的回收主要分为新生代对象和老生代对象,而且新生代和老生代的垃圾回收策略也不相同

  2. 新生代

    新生代对象内存空间一分为二,分别是空间from和空间to,新生代对象会先存储在from空间,当一轮GC后,使用标记整理算法对from空间进行垃圾处理和空间内存优化,清除完成后,将from空间复制到to空间,并将from空间与to空间进行交换。

  3. 老生代

    老生代对象回收主要使用:标记清除,标记整理和增量标记算法。老生代区域主要使用标记清除算法来回收垃圾空间,当在晋升的过程中老生代区域内存空间出现不足的情况时就会使用标记整理算法来整理碎片化空间。在标记的过程使用的是增量标记的方式来对对象进行标记。

13. 描述增量标记算法在何时使用及工作原理

img

 

如图所示,与标记清除的标记过程不同,增量标记在标记的过程并不是连贯的,它会将标记的过程拆分成多个小的过程,分开标记。这么做的原因是,在标记的过程中,js引擎不会执行代码,且老生代区域可存储的对象较多,当标记的对象太多的情况,可能会造成js执行卡顿的情况,但如果使用增量标记的方式,将标记拆分成多个小的部分,就可以较好的优化这种情况。(但标记清除和增量标记的清除垃圾的过程都是一次性清除)

原文地址:https://www.cnblogs.com/ndh074512/p/14951578.html