简答题
一、请说出下列最终的执行结果,并解释为什么?
var a = [];
for (var i =0; i< 10; i++) { // i 是在全局作用域下的变量, 循环中, i被不断地重新赋值, 最终是 10即(window.i = 10)
a[i] = function () { // 循环的时候,函数未执行
console.log(i)
}
}
a[6]() // 10 函数执行,当前的this指向window,window.i = 10
二、请说出下列最终的执行结果,并解释为什么?
var tmp = 123;
if (true) {
console.log(tmp) // 因为在最近的{}作用域里,有定义tmp,所以不会使用全局的tmp. 在这作用域里,这时候还没定义就使用所以会报错(未定义)
let tmp // tmp 是局部作用域, 就近原则
}
三、结合ES6新语法、用最简单的方式找出数组中的最小值
let arr = [12, 34, 32, 89, 4]
function getSmall (array) {
return array.reduce( (accumulator, currentValue) => { // 箭头函数
return accumulator >= currentValue ? currentValue : accumulator
})
}
console.log(getSmall(arr))
四、请说出var, let, const 三中声明变量方式之间的具体区别
-
var 没有块级作用域概念,在作用域中会变量提升(提升到作用域的顶部, 创建过程、和初始化都被提升)。在作用域中, 可以先使用后声明,同一变量可以重复声明, 挂在全局对象下、可以被重新赋值
-
let 块级作用域, 声明之前不可以使用,形成暂时性死区。 同一个块级作用域下, 同一变量不可重复声明,不属于全局对象, 也有变量提升(创建被提升,初始化没有被提升),可以被重新赋值
-
const 和let 的区别是不可以被重新赋值
五、请说出下列代码最终输出的结果,并解释为什么
var a = 10;
var obj = {
a: 20,
fn () { // obj调用fn这时这里的this 指向obj
setTimeout(() => { //箭头函数本身没有this, 会把该作用域的上下文绑定该作用域上,所以这里的this也就指向了obj
console.log(this.a) // 所以20
})
}
}
obj.fn()
六、简述Symbol类型的用途
- 定义常量
- 定义对象的toString结果
- 作为对象属性名(key)Symbol是独一味二的
- 模拟实现私有成员
- 注册和获取全局Symbol
- 迭代器
七、说说什么是浅拷贝,什么是深拷贝
浅拷贝:拷贝的是指向对象的引用(对象在堆中的地址)。修改会直接修改对象。原始数据类型没有深拷贝、浅拷贝之分 深拷贝:拷贝整个对象的值(对象在堆中的数据), 修改的是复制的对象, 不会影响原对象。
八、请简述TypeScript与JavaScript之间的关系
TypeScript 是 JavaScript 的一个超集,支持 ES+ ts 在 js 之上,添加了类型系统,ts最终会编译成js
九、请谈谈你所认为的TypeScript优缺点
优点
* 类型系统。增加了代码的可读性和可维护性,在编译时候就可发现大部分的错误(语法,类型),增强编辑器的功能
* 包容性,js文件可以直接改成 ts 文件,不定义类型可自动推论类型,可以定义几乎一切类型,ts 编译报错时也可以生成 js 文件,兼容第三方库,即使不是用ts编写的
* 有活跃的社区,大多数的第三方库都可提供给 ts 的类型定义文件,完全支持 es6 规范
缺点
* 增加学习成本,需要理解接口(Interfaces)和泛型(Generics),类(class),枚举类型(Enums)
* 短期增加开发成本,增加类型定义,但减少维护成本。小项目比较不划算
* 和有些库结合时不是很完美, 需要自己声明类型
十、描述引用计数的工作原理和优缺点
原理
为对象的引用计数。根据当前引用的引用数是否为0, 引用关系改变了修改引用数, 引用数为0 的时候, 立即回收
优点
- 发现垃圾立即回收
- 最大限度减少程序暂停
缺点
- 无法回收循环引用的对象
- 时间开销大
十一、描述标记整理算法的工作流程
- 分标记和清除整理两个阶段
- 标记阶段:遍里所有所有对象找标记活动对象
- 清除阶段:遍里所有对象,先执行整理移动对象位置,然后清除没有标记对象
十二、描述V8中新生代存储区垃圾回收的流程
- 回收过程采用复制算法+标记整理
- 新生代内存分区为两个等大小的空间
- 使用空间From, 空闲空间为TO
- 活动对象存储在From空间
- 标记整理后将活动对象拷贝至To
- From 和 To 交换空间完成释放
十三、描述增量标记算法在何时使用及工作原理
何时使用
增量标记算法是V8引擎清除老生代对象是为提高清除效率优化时使用的,因为在进行垃圾回收的操作式,也是会阻塞程序的执行, 所以在清除老生代垃圾是在程序执行的空档期去执行回收垃圾操作,此时就可以使用增量标记算法。它是将当前一整段的垃圾回收操作,分成多个小段组合法去完成。实现垃圾回收和程序执行交替完成。这样可以让时间消耗更合理,效率优化
工作原理
- JS程序执行过程中,会伴随着垃圾回收的工作
- 当垃圾回收工作时,需要遍历对象进行标记,此时不需要将所有对象进行标记,可以先将直接可达的对象进行标记,标记完成后暂停标记
- 然后让JS程序执行一会,再让GC机制去做二步标记,将间接可达的对象进行标记,标记完成后暂停标记
- 重复以上两个操作,让程序执行和垃圾回收的标记操作交替执行,来达到优化效率和提升用户体验的目的
- 直到标记全部完成后,执行垃圾回收
示意图