1 执行结果及为什么
var a = []for(var i=0;i<10;i++) {a[i] = function() {console.log(i)}}a[6](); // 10
解析:
for循环内部,每次循环都会给数组赋值进去,赋值的是一个函数,函数在初始化的时候会产生作用域链,作用域链里面有当前函数的作用域,父级作用域;循环完毕后,数组内的每个值是引用的一个地址;当执行a[6]的时候,调用函数,执行栈里面会压入当前函数,执行console的时候,去寻找i变量,当前作用域下没有,便沿着作用域链往上找,找到全局作用域下有i,此时i的值是循环执行完毕后的最后的值,就是10,所以此时打印10
2 执行结果及为什么
var tmp = 123;if(true) {console.log(temp)let tmp;}// 报错tmp undefined
解析:
let在的地方,有块级作用域,存在暂时性死区,未声明不可直接引用,不会有变量提升
3 用es6最简单的方法找出最小var arr = [12, 34, 32, 89, 4];
var arr = [12, 34, 32, 89, 89, 4];console.log('way1----', arr.sort((a, b) => a - b)[0]);let aa = Infinity;for (let item of arr) {item <= aa ? (aa = item) : (aa = aa);}console.log('way2----', aa);const bb = arr.reduce((a, b) => {return a > b ? b : a}, arr[0]);console.log('way3----',bb);
4 var,let ,const 区别
var 声明变量,可改,可先引用后声明,有变量提升,可重复申明;
let 声明变量,产生块级作用域,可改,在当前作用域下唯一声明,必须先声明后引用
const 声明常量,原始类型不可改,引用类型不可改地址;当前作用域下唯一申明,声明后必须初始化,必须先声明后引用;
5 执行结果及为什么
var obj = {a: 20,fn() {setTimeout(()=> {console.log(this.a)})}}obj.fn(); // 20
解析:
监听函数内没有this指针问题,里面的this为父级作用域this,此处父级是fn,fn的this指向当前调用的obj,所以返回20;
如果将箭头函数换为function,则在node环境下this指向Timeout,会返回undefined;浏览器环境下指向window,会返回10;
6 symbol类型用途
目前Symbol主要是作为对象的唯一键来使用;
7 浅拷贝和深拷贝
浅拷贝就是复制对象的引用;深拷贝就是复制对象的内容并开辟新的地址存储这个内容;
8 Typescript和JavaScript的关系
typescript是JavaScript的超集,兼容最新的ECMAScript语法,编译后可兼容到ECMAScript3的版本;对于多人合作项目,typescript尤其能提升效率;其克服了弱类型和动态类型导致的问题,在编译阶段就能发现错误,是JavaScript的终极解决方案;
9 typescript的优缺点
优点:提前发现错误;减少人为约定,加强语言层面的约束,提高开发效率;
缺点:在初期会有很多额外的定义类型工作,增加了学习负担
10 引用计数的工作原理和优缺点
引用计数就是每有一个活动对象,都会产生一个引用计数,对象每一次引用变化,计数就随之改变,直到计数为0,对象就会被视为垃圾,等待回收;
优点:立即执行,发现垃圾立即回收
缺点:对于循环引用无法释放,资源占用多
11 标记整理算法的工作流程
标记整理算法和标记清除算法在标记阶段是一致的,GC开始时都会标记所有活动对象,对于未标记的对象视为垃圾;清除阶段,标记清除算法,会直接释放非活动对象的空间;标记整理算法,会先移动活动对象,将活动对象和非活动对象的地址尽量变为连续,然后再清除非活动对象;
12 V8新生代存储区垃圾回收的流程
新生代会划分为相同大小的两个区from使用区和to空闲区,当from容量接近阀值时,from区的对象会被移动到to区,然后因为to区有了备份,会直接释放from区,这时候from和to区互换,等待下一轮GC;to区的容量达到25%,会把to区的活动对象复制到老生代(晋升)
13 增量标记算法何时使用及工作原理
增量标记算法在老生代的垃圾回收时使用,程序执行一段时间后,触发GC算法,就开始执行遍历所有对象的操作,并且遍历的过程中要标记对象;如果对象可以看成树形,则第一层的对象先标记;然后暂停标记,让程序继续执行一段时间;然后继续标记第二层的对象,标记完继续让程序执行;一直交替,直到所有标记工作完成,就暂停程序执行开始清除工作;清除完毕后,程序继续执行;循环往复;
