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…