Open libin1991 opened 6 years ago
console.log(a) // undefined var a = 1; var getNum = function() { a = 2; } function getNum() { a = 3; } console.log(a) // 1 getNum() console.log(a) // 2
这道题主要考查声明提升和函数声明先于变量声明这两个知识点。在解析这个js片段的时候是按照这样的顺序:
// 声明提升 function getNum() { a = 3; } var a; var getNum; // console.log(a); a = 1; getNum = function() { a = 2; } console.log(a) getNum() console.log(a)
这样就很清晰了,第一次输出a的时候还没有赋值,所以是undefined。第二次的不用说了。第三次输出2是因为,一开始getNum是指向一个函数的,后来又声明赋值成了一个函数表达式。
undefined
getNum
// 每隔一秒输出一次i值 for(var i = 0; i < 5; i++){ // TODO }
此题主要考查闭包和js执行机制。以下几种解法:
大概1秒输出一次的版本:
// 利用立即执行函数形成闭包 (function(i){ setTimeout(function() { console.log(i) }, i * 1000)})(i)
// 利用setTimeout的第三个参数形成闭包 setTimeout(function(i) { console.log(i) }, i * 1000, i)
// 如果不是题目中指定了var,利用ES6的let就简单多了 for(let i = 1; i < 5; i++) { setTimeout(function(){ console.log(i) }, i * 1000) }
// 再看ES7版本 const sleep = (time) => new Promise((resolve, reject) => setTimeout(resolve, time)); (async function(){ for(let i=0;i<10;i++){ await sleep(1000); console.log(i); } })()
之所以是说是大概,是因为setTimeout并不是延时多少秒后执行函数,而是多少秒后把函数扔进事件队列中等待执行,如果此时队列里有其他任务 的话那就不是精确的1秒了。
setTimeout
关于js执行机制,看这里这一次,彻底弄懂 JavaScript 执行机制
再看比较精确的1秒版本:
for(var i =0; i < 5; i++) { var time = new Date(); while(new Date() - time < 1000) { } console.log(i) }
直接阻塞线程一秒钟,简单粗暴有木有~
var a = {} var b = { key: "a" } var c = { key: "c" } a[b] = "123"; a[c] = "456"; console.log(a[b]) // 456
这题主要考查对象。其实这里a[b]和a[c]中的b、c都会调用object.prototype.toString(),都变成了[object Object],这样就与对象中的key值无关了。所以a[b]和a[c]的指向是相同的。
a[b]
a[c]
object.prototype.toString()
[object Object]
var f = function() { var c = "ccc"; return { a: function() { return c; }, b: function(d) { c = d; } } }() console.warn(f.a()) // ccc console.warn(f.c) // undefined console.warn(f.b("www")) // undefined console.warn(f.a()) // www
这题主要考查的是执行上下文中的作用域链。我们要注意到函数表达式后的那个函数执行符——(),它是个立即执行函数,也就是说f是个包含a、b属性的对象。
console.warn(f.a())
当a()的执行上下文被激活时,作用域和变量对象被确定,c是个自由变量,需要在作用域链中向上查找,然受在父级作用域中找到,所以输出“ccc”。
console.warn(f.c)
这个就不用说啦,f中没有c这个属性,取不到当然返回undefined。
console.warn(f.b("www"))
同第一行一样,修改的是父级作用域中的c,但由于没有返回值所以输出的是undefined。
数组去重 输入[1,2,3,1,'1','2',2]返回[1,2,3,'1','2']。 这个嘛方法就很多啦。
[1,2,3,1,'1','2',2]
[1,2,3,'1','2']
(function(arr){ console.log([...(new Set(arr))]) })([1,2,3,1,'1','2',2])
有两个小写字符串s1、s2,s2是s1经过打乱后增加一个小写字符得到的, 编程得出s2中增加的字符,算法时间复杂度最好接近O(n)(如s1是'abc',s2是'cbad',那么增加的字符为‘d’)。
笔者关于这道题的思考,首先是考虑到增加的字符可能是s1中已经存在的,那通过遍历+indexOf()的方案也就没用了,所以笔者在写这道题的时候考虑到s1、s2只有一个字符之差,索性把s1、s2中的字符都填入一个对象中统计每个字符的个数,个数为奇数的就是那个多出来的字符了。上代码:
indexOf()
var s1 = "aaabweddccc"; var s2 = "aaaewwbcccdd"; (function(a,b){ let aLen = a.length; let bLen = b.length; let hash = {}; for(let i = 0; i < aLen; i++) { hash[a[i]] ? hash[a[i]]++ : hash[a[i]] = 1; hash[b[i]] ? hash[b[i]]++ : hash[b[i]] = 1; } hash[b[aLen]] ? hash[b[aLen]]++ : hash[b[aLen]] = 1; console.log(hash) for(let j in hash) { if(hash[j] % 2 !== 0) { console.log(j) } } })(s1,s2)
运行结果:
总共就6道题,考的比较基础,包括:
欢迎大家在评论区中对以上内容斧正~
掘金技术征文活动链接: juejin.im/post/5aaf2a…
第一题
console.log(a) // undefined var a = 1; var getNum = function() { a = 2; } function getNum() { a = 3; } console.log(a) // 1 getNum() console.log(a) // 2
这道题主要考查声明提升和函数声明先于变量声明这两个知识点。在解析这个js片段的时候是按照这样的顺序:
// 声明提升 function getNum() { a = 3; } var a; var getNum; // console.log(a); a = 1; getNum = function() { a = 2; } console.log(a) getNum() console.log(a)
这样就很清晰了,第一次输出a的时候还没有赋值,所以是
undefined
。第二次的不用说了。第三次输出2是因为,一开始getNum
是指向一个函数的,后来又声明赋值成了一个函数表达式。第二题
// 每隔一秒输出一次i值 for(var i = 0; i < 5; i++){ // TODO }
此题主要考查闭包和js执行机制。以下几种解法:
大概1秒输出一次的版本:
// 利用立即执行函数形成闭包 (function(i){ setTimeout(function() { console.log(i) }, i * 1000)})(i)
// 利用setTimeout的第三个参数形成闭包 setTimeout(function(i) { console.log(i) }, i * 1000, i)
// 如果不是题目中指定了var,利用ES6的let就简单多了 for(let i = 1; i < 5; i++) { setTimeout(function(){ console.log(i) }, i * 1000) }
// 再看ES7版本 const sleep = (time) => new Promise((resolve, reject) => setTimeout(resolve, time)); (async function(){ for(let i=0;i<10;i++){ await sleep(1000); console.log(i); } })()
之所以是说是大概,是因为
setTimeout
并不是延时多少秒后执行函数,而是多少秒后把函数扔进事件队列中等待执行,如果此时队列里有其他任务 的话那就不是精确的1秒了。关于js执行机制,看这里这一次,彻底弄懂 JavaScript 执行机制
再看比较精确的1秒版本:
for(var i =0; i < 5; i++) { var time = new Date(); while(new Date() - time < 1000) { } console.log(i) }
直接阻塞线程一秒钟,简单粗暴有木有~
第三题
var a = {} var b = { key: "a" } var c = { key: "c" } a[b] = "123"; a[c] = "456"; console.log(a[b]) // 456
这题主要考查对象。其实这里
a[b]
和a[c]
中的b、c都会调用object.prototype.toString()
,都变成了[object Object]
,这样就与对象中的key值无关了。所以a[b]
和a[c]
的指向是相同的。第四题
var f = function() { var c = "ccc"; return { a: function() { return c; }, b: function(d) { c = d; } } }() console.warn(f.a()) // ccc console.warn(f.c) // undefined console.warn(f.b("www")) // undefined console.warn(f.a()) // www
这题主要考查的是执行上下文中的作用域链。我们要注意到函数表达式后的那个函数执行符——(),它是个立即执行函数,也就是说f是个包含a、b属性的对象。
当a()的执行上下文被激活时,作用域和变量对象被确定,c是个自由变量,需要在作用域链中向上查找,然受在父级作用域中找到,所以输出“ccc”。
这个就不用说啦,f中没有c这个属性,取不到当然返回
undefined
。console.warn(f.b("www"))
同第一行一样,修改的是父级作用域中的c,但由于没有返回值所以输出的是undefined。
第五题
数组去重 输入
[1,2,3,1,'1','2',2]
返回[1,2,3,'1','2']
。 这个嘛方法就很多啦。(function(arr){ console.log([...(new Set(arr))]) })([1,2,3,1,'1','2',2])
第六题
笔者关于这道题的思考,首先是考虑到增加的字符可能是s1中已经存在的,那通过遍历+
indexOf()
的方案也就没用了,所以笔者在写这道题的时候考虑到s1、s2只有一个字符之差,索性把s1、s2中的字符都填入一个对象中统计每个字符的个数,个数为奇数的就是那个多出来的字符了。上代码:var s1 = "aaabweddccc"; var s2 = "aaaewwbcccdd"; (function(a,b){ let aLen = a.length; let bLen = b.length; let hash = {}; for(let i = 0; i < aLen; i++) { hash[a[i]] ? hash[a[i]]++ : hash[a[i]] = 1; hash[b[i]] ? hash[b[i]]++ : hash[b[i]] = 1; } hash[b[aLen]] ? hash[b[aLen]]++ : hash[b[aLen]] = 1; console.log(hash) for(let j in hash) { if(hash[j] % 2 !== 0) { console.log(j) } } })(s1,s2)
运行结果:
总结
总共就6道题,考的比较基础,包括:
欢迎大家在评论区中对以上内容斧正~
掘金技术征文活动链接: juejin.im/post/5aaf2a…