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秒输出一次的版本:bash
// 利用当即执行函数造成闭包
(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(var i = 0; i < 5; i++){
await sleep(1000);
console.log(i);
}
})()
复制代码
之因此是说是大概,是由于setTimeout
并非延时多少秒后执行函数,而是多少秒后把函数扔进事件队列中等待执行,若是此时队列里有其余任务 的话那就不是精确的1秒了。数据结构
关于js执行机制,看这里这一次,完全弄懂 JavaScript 执行机制闭包
再看比较精确的1秒版本:async
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
复制代码
这题主要考查对象。js的对象中的全部属性key都是字符串类型(这是和Map数据结构的区别之一,Map的key能够是任何类型),并且会强制转换,因此a[b]
和a[c]
中的b、c都会调用object.prototype.toString()
强制转换成字符串,都变成了[object Object]
,这样就与对象中的key值无关了。因此a[b]
和a[c]
的指向是相同的。post
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属性的对象。ui
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']
。 这个嘛方法就不少啦。
(function(arr){
console.log([...(new Set(arr))])
})([1,2,3,1,'1','2',2])
复制代码
利用Map结构的key能够是任意类型这个特性,能很好的区分字符'1'和数字1,而普通对象的key值是字符串类型,没法区分这二者。
(function(arr) {
let hash = new Map();
arr = arr.reduce((item, value) => {
hash.has(value) ? '' : hash.set(value, true) && item.push(value)
return item;
}, [])
console.log(arr)
})([1,2,3,1,'1','2',2])
复制代码
有两个小写字符串s一、s2,s2是s1通过打乱后增长一个小写字符获得的, 编程得出s2中增长的字符,算法时间复杂度最好接近O(n)(如s1是'abc',s2是'cbad',那么增长的字符为‘d’)。
笔者关于这道题的思考,首先是考虑到增长的字符多是s1中已经存在的,那经过遍历+indexOf()
的方案也就没用了,因此笔者在写这道题的时候考虑到s一、s2只有一个字符之差,索性把s一、s2中的字符都填入一个对象中,统计每一个字符的个数,个数为奇数的就是那个多出来的字符了。(另外欢迎在评论区中给出更优解)上代码:
var s1 = "aaabweddccc";
var s2 = "aaaewwbcccdd";
(function(a,b){
let all = a + b;
let allLen = all.length;
let hash = {};
for(let i = 0; i < allLen; i++) {
hash[all[i]] ? hash[all[i]]++ : hash[all[i]] = 1;
}
console.log(hash)
for(let j in hash) {
if(hash[j] % 2 !== 0) {
console.log(j)
}
}
})(s1,s2)
复制代码
运行结果:
这个方法是后来想到的。思路是这样的,若是没有插入那个额外的字符以前,对两个字符串进行排序后,两字符串对应位置的字符确定是相同的,插入一个字符以后,一定有个位置的字符不匹配。
(function(a,b){
a = a.split("").sort()
b = b.split("").sort()
for(let i = 0, len = b.length; i < len; i++) {
if(a[i] !== b[i])
console.log(b[i])
}
})(s1,s2)
复制代码
运行结果:
总共就6道题,考的比较基础,包括:
欢迎你们在评论区中对以上内容斧正~
掘金技术征文活动连接: juejin.im/post/5aaf2a…