第 1题:输出以下代码的执行结果并解释为什么
var a = {n: 1}; var b = a; a.x = a = {n: 2}; console.log(a.x) console.log(b.x)
答案为:undefined {n:2}
首先,a和b同时引用了{n:2}对象,接着执行到a.x = a = {n:2}语句,尽管赋值是从右到左的没错,但是.的优先级比=要高,所以这里首先执行a.x,相当于为a(或者b)所指向的{n:1}对象新增了一个属性x,即此时对象将变为{n:1;x:undefined}。之后按正常情况,从右到左进行赋值,此时执行a ={n:2}的时候,a的引用改变,指向了新对象{n:2},而b依然指向的是旧对象。之后执行a.x = {n:2}的时候,并不会重新解析一遍a,而是沿用最初解析a.x时候的a,也即旧对象,故此时旧对象的x的值为{n:2},旧对象为 {n:1;x:{n:2}},它被b引用着。
后面输出a.x的时候,又要解析a了,此时的a是指向新对象的a,而这个新对象是没有x属性的,故访问时输出undefined;而访问b.x的时候,将输出旧对象的x的值,即{n:2}。
第 2 题:ES6 代码转成 ES5 代码的实现思路是什么
1.将代码字符串解析成抽象语法树,即所谓的 AST
2.对 AST 进行处理,在这个阶段可以对 ES6 代码进行相应转换,即转成 ES5 代码
3.根据处理后的 AST 再生成代码字符串
第 3 题:数组编程题
//随机生成一个长度为 10 的整数类型的数组,例如 [2, 10, 3, 4, 5, 11, 10, 11, 20], //将其排列成一个新数组,要求新数组形式如下,例如 [[2, 3, 4, 5], [10, 11], [20]]。 //区间分布 let arr = [2, 10, 3, 4, 5, 11, 10, 11, 20]; function getArr(arr){ let temparr = [... new Set(arr.sort((a,b)=>a-b))] let map = new Map(); temparr.forEach(item=>{ const key = Math.floor(item/10); const group = map.get(key) || [] group.push(item); map.set(key,group) }) return [...map.values()] } getArr(arr)
第 4 题:数组里面有10万个数据,取第一个元素和第10万个元素的时间相差多少
JavaScript 没有真正意义上的数组,所有的数组其实是对象,其“索引”看起来是数字,其实会被转换成字符串,作为属性名(对象的 key)来使用。所以无论是取第 1 个还是取第 10 万个元素,都是用 key 精确查找哈希表的过程,其消耗时间大致相同。
第 5题:输出以下代码运行结果
// example 1 var a={}, b='123', c=123; a[b]='b'; a[c]='c'; console.log(a[b]); --------------------- // example 2 var a={}, b=Symbol('123'), c=Symbol('123'); a[b]='b'; a[c]='c'; console.log(a[b]); --------------------- // example 3 var a={}, b={key:'123'}, c={key:'456'}; a[b]='b'; a[c]='c'; console.log(a[b]);
这题考察的是对象的键名的转换。 对象的键名只能是字符串和 Symbol 类型。 其他类型的键名会被转换成字符串类型。 对象转字符串默认会调用 toString 方法。 // example 1 var a={}, b='123', c=123; a[b]='b'; // c 的键名会被转换成字符串'123',这里会把 b 覆盖掉。 a[c]='c'; // 输出 c console.log(a[b]); // example 2 var a={}, b=Symbol('123'), c=Symbol('123'); // b 是 Symbol 类型,不需要转换。 a[b]='b'; // c 是 Symbol 类型,不需要转换。任何一个 Symbol 类型的值都是不相等的,所以不会覆盖掉 b。 a[c]='c'; // 输出 b console.log(a[b]); // example 3 var a={}, b={key:'123'}, c={key:'456'}; // b 不是字符串也不是 Symbol 类型,需要转换成字符串。 // 对象类型会调用 toString 方法转换成字符串 [object Object]。 a[b]='b'; // c 不是字符串也不是 Symbol 类型,需要转换成字符串。 // 对象类型会调用 toString 方法转换成字符串 [object Object]。这里会把 b 覆盖掉。 a[c]='c'; // 输出 c console.log(a[b]);