# fed-e-task-01-02 **Repository Path**: ternence07/fed-e-task-01-02 ## Basic Information - **Project Name**: fed-e-task-01-02 - **Description**: No description available - **Primary Language**: JavaScript - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2020-08-29 - **Last Updated**: 2020-12-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ### 简单题 ##### 一、请说出下列的执行结果,并解释为什么 ```js var a = [] for (var i = 0; i < 10; i += 1) { a[i] = function () { console.log(i) } } a[6]() ``` 【答】10。var声明的变量,其作用域为该语句所在函数,且存在变量提升的现象。 在循环绑定事件过程中,var定义的变量无法保存,循环会在瞬间执行完。此题中a[6]所值的是输出console.log(i),再执行a[6]()的时候,i已经通过循环变成了10,所有输出为10。 ##### 二、请说出下列的执行结果,并解释为什么 ```js var tmp = 123 if(true){ console.log(tmp) let tmp } ``` 【答】执行失败,var没有块级作用域,而let有。let定义的变量不会预解析,必须先声明再使用。在执行过程中{}所访问带变量是let所定义的块级的变量。 ##### 三、结合ES6新语法,用最简单的方式找出数组中的最小值 ```js var arr = [12, 34, 32, 89, 4] const findMin = (arr) =>Math.min(...arr) console.log(findMin(arr)) ``` ##### 四、请详细说明var、let、const 三种声明变量方式之间的具体差别 【答】 ###### var 1. var定义的变量会预解析 ,先使用后声明不会报错,会输出underfine 2. var定义的变量可以反复定义,后面的会覆盖前面的 3. var在循环中使用的时候,循环体外依然可以使用 4. 在循环绑定事件过程中,var定义的变量无法保存,循环会在瞬间执行完 ###### let 1. let定义的变量不会预解析,必须先声明再使用,否则会报错 2. let不能定义已经定义过的变量 3. let是块级作用域,函数内部使用let定义后,对函数外部无影响,简单说就是在一个{}里面生效 4. 由于let是块级作用域,在循环绑定事件过程中let会在这个循环中生效,再次循环时let会重新定义生效 ##### const 1. const定义的变量不会预解析,必须先声明再使用,否则会报错 2. const定义的变量不允许修改 ##### 五、请说出下列的执行结果,并解释为什么 ```js var a = 10 var obj = { a: 20, fn() { setTimeout(() => { console.log(this.a) }) } } obj.fn() ``` 【答】20。obj.fn()当前this指向的就是对象本身,所有在this.a的值也就是obj定义的属性a的值 ##### 六、简述Symbol类型的用途 【答】 symbol 是一种无法被重建且无法被改变的基本类型 。用途如下 1. symbol作为对象的属性名 2. 阻止对象属性名冲突。 当两个不同的库要读取对象的一些原始属性时,或许它们都想要类似的标识符。如果只是简单的使用字符串 id 作为 key,这将会有很大的风险,因为它们的 key 完全有可能相同。 3. 模拟私有属性 ##### 七、说说什么是浅拷贝,什么是深拷贝 【答】 只会将对象的各个属性进行依次复制,并不会进行递归复制,深拷贝是对对象以及对象的所有子对象进行拷贝 。如何区分深浅拷贝,就是是假设B复制了A,当修改A时,看B是否会发生变化,如果B也跟着变了,说明这是浅拷贝,如果B没变,那就是深拷贝。 实现浅拷贝的方法: 1. for···in只循环第一层 2. Object.assign方法 3. 直接用=赋值 实现深拷贝的方法: 1. 采用递归去拷贝所有层级属性 2. 采用递归去拷贝所有层级属性 3. lodash函数库实现深拷贝 4. Reflect法 5. 手动实现深拷贝 6. 如果对象的value是基本类型的话,也可以用Object.assign来实现深拷贝,但是要把它赋值给一个空对象 7. 用slice,concat实现对数组的深拷贝 8. 直接使用var newObj = Object.create(oldObj),可以达到深拷贝的效果 9. 使用扩展运算符实现深拷贝 ##### 八、简述TypeScript和JavaScript之间的关系 【答】 JavaScript是一种基于客户端浏览器的,基于对象、事件驱动式的脚本语言 。 TypeScript是JavaScript类型的超类,它可以编译成纯JavaScript。可以在任何浏览器、任何计算机和任何操作系统上运行 。 可以使用JavaScript中的所有代码和编程概念,TypeScript是为了使JavaScript的开发变得更加容易而创建的。 应对大型开发项目时,使用 TypeScript 更加合适。如果有一个相对较小的编码项目,似乎没有必要使用 TypeScript,只需使用灵活的 JavaScript 即可。 ##### 九、谈谈TypeScript的优缺点 【答】 优势: 1. 静态类型化,允许开发人员编写更健壮的代码并对其进行维护 2. 大型的开发项目,使用TypeScript工具来进行重构更容易、便捷 3. 类型安全,在编码期间检测错误的功能,而不是在编译项目时检测错误 4. 干净的ECMAScript6代码,自动完成和动态输入等因素有助于提高开发人员的工作效率 缺点: 1. 有一定的学习成本,需要理解接口(Interfaces)、泛型(Generics)、类(Classes)、枚举类型(Enums)等前端工程师可能不是很熟悉的概念 2. 短期可能会增加一些开发成本,毕竟要多写一些类型的定义,不过对于一个需要长期维护的项目,TypeScript 能够减少其维护成本 3. 集成到构建流程需要一些工作量 4. 可能和一些库结合的不是很完美 ##### 十、描叙引用计数的工作原理和优缺点 【答】原理: 在每一个对象上记录这个对象被引用的次数,只要有任何一个对象引用了次对象,这个对象的计数器就+1,取消对这个对象的引用时,计数器就-1。任何一个时刻,如果该对象的计数器为0,那么这个对象就是可以回收的 。 优点: 1. 发现垃圾立即回收 2. 最大限度减少程序暂停时间 缺点: 1. 无法回收循环引用的对象 2. 事件开销大 ##### 十一、描述标记整理算法的工作流程 【答】原理: 首先标记出所有需要回收的对象,让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存。 优点: 1. 减少碎片化空间 缺点: 1. 不能立即回收垃圾对象 ###### 十二、描叙V8中新生代存储区垃圾回收的流程 【答】主要使用复制算法和标记整理算法。先在新生代区,将堆内存对半分,一半处于使用(即From区),另一半处于闲置(即To区),平时在From区用标记整理算法进行操作。到了要回收的时候,检测From区的对象,存活的对象复制到To区,然后From区被释放了,之后对To区和From区调换名字,继续重复之前操作 ##### 十三、描叙增量标记算法在何时使用及其工作原理 【答】原理: 通过对进程间冲突的妥善处理,允许垃圾收集进程以分阶段的方式完成标记、清理或复制工作。增量算法的具体机制可以用不同,但其思想都是把堆栈分为多个域,每次仅从一个域收集垃圾,从而造成较小的应用程序中断。