简答题

一、请说出下列最终的执行结果,并解释为什么。

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

最终结果是在控制台输出10;for循环中使用var定义变量没有块级作用域,在a[6]方式执行的时候会根据js的词法作用域向上查找找到的i是已经经过++操作的10;

二、请说出下列最终的执行结果,并解释为什么。

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

最终结果会出现引用错误;在if的代码块中出现了let声明变量,所以在if代码块中就出现了tmp变量的暂时性死区,js的编译器会抛出引用错误;

三、结合ES6新语法,用最简单的方式找出数组中的最小值。

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

四、请详细说明var, let, const三种声明的方式之间的具体差别。

var声明变量是会出现变量提升,而let和const不会;var可以重复定义,而let和const不行;let和var定义的变量可以被改变,而const不可以;

五、请说出下面代码最终输出的结果,并解释为什么。

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

obj.fn()

执行的结果是20;箭头函数不改变运行时this的指向,所以log中的this指向距离最近的fn中的this,以上代码等同于

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

六、简述 Symbol 类型的用途。

Symbol可以声明一个独一无二的变量可以用作对象的键,可以用来做依赖注入中的服务名称或者控制器名称。同时Symbol中中定义了一些常量可以用来迭代数组等等。

七、说说什么是浅拷贝,什么是深拷贝?

浅拷贝是指将"引用"的地址存储在变量中,该地址中的某一些变化可以通过新变量访问;深拷贝是将"引用"通过递归等手段将其中"值"分别赋值;

八、请简述Typescript 和Javascript之间的关系。

javascript可以直接运行在V8引擎中,而ts需要通过tsc将ts代码编译成js代码才能运行在v8上;在es6没有普及的时候可以通过ts使用javascript中的高级语法;

九、请谈谈你所认为的Typescript优缺点。

typescript可以大大降低在生产中类型引起的一系列问题,因为在ts编译的时候会进行类型检查;在ts中可以自由的使用js中的一些没有普及的语法;但是ts学习成本比较高,在已有的项目中使用ts会存在大量代码重构带来的高成本;

十、描述引用计数的工作原理和优缺点。

引用计数用来记录当前有多少指针指向同一块动态分配的内存。当有指针指向这块内存时,计数器加1;当指向此内存的指针销毁时,计数器减1。当引用计数为0时,表示此块内存没有被任何指针指向,此块被共享的动态内存才能被释放。 当变量循环引用时无法判断变量是否需要销毁,导致无法判断内存泄漏;优点就是算法相对来说比较简单容易实现;发现垃圾时立即回收;最大限度减少程序暂停

十一、描述标记整理算法的工作流程。

标记整理可以看做是标记清除的加强算法;标记阶段的操作和标记清除一致;清除阶段会先执行整理,移动对象位置,整理内存;

十二、描述V8中新生代存储区垃圾回收的流程。

V8内存一分为二,小空间用于存储新生代对象(32M|16M)用于回收存活时间比较短的对象;回收过程采用复制算法+标记整理;新生代内存区分为二个等大小空间;使用空间为From,空闲空间为To;活动对象的存储于From空间;标记整理后将活动对象拷贝To;From与To交换空间完成释放。

十三、描述增量标记算法在何时使用以及工作原理。

在V8清除老生代对象时为提高清除效率优化时使用;清除时,程序执行然后遍历对象进行标记,之后交替执行程序和增量标操作,标记完成后,进行清除操作,完成垃圾回收;