記一次前端筆試題 | 掘金技術徵文

Gesangs發表於2019-03-04

第一題

    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(var i = 0; i < 5; 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
複製程式碼

這題主要考查物件。js的物件中的所有屬性key都是字串型別(這是和Map資料結構的區別之一,Map的key可以是任何型別),而且會強制轉換,所以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屬性的物件。

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])
複製程式碼

第六題

有兩個小寫字串s1、s2,s2是s1經過打亂後增加一個小寫字元得到的,
程式設計得出s2中增加的字元,演算法時間複雜度最好接近O(n)(如s1是`abc`,s2是`cbad`,那麼增加的字元為‘d’)。

解法一

筆者關於這道題的思考,首先是考慮到增加的字元可能是s1中已經存在的,那通過遍歷+indexOf()的方案也就沒用了,所以筆者在寫這道題的時候考慮到s1、s2只有一個字元之差,索性把s1、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道題,考的比較基礎,包括:

  • 宣告提升
  • 閉包
  • 執行上下文
  • js執行機制
  • ……

歡迎大家在評論區中對以上內容斧正~

掘金技術徵文活動連結: juejin.im/post/5aaf2a…

相關文章