熱乎的前端筆試/面試/跳坑筆記(指南)

Vincent Ko發表於2018-07-22

寫在前面的話

本人不是高手,也是小白一隻。在學習的過程中,總是反覆的遺忘、記憶、練習、遺忘..因此決定把走過的坑,以及經歷的筆試開始慢慢的總結,會不斷的更新和新增,原文地址在github,覺得不錯的小夥伴,記得給個star哦,共同進步~~

更新地址:傳送門

前端面試&筆試&錯題指南

Css相關

1. display:none與visibility:hidden的區別(2018拼多多前端筆試真題)

答案:在視覺效果上,兩者是相同的,但是對於操作dom上是不同的 。 dispaly:none 會讓dom的整個寬、高等相關位置元素失效,整個消失; visibility:hidden 只是讓該元素不可見,但是width以及原有位置是不會改變的

javascript

1. 基本問題

1) 是否可以使用 typeof bar === 'object'來檢測bar是不是object型別,有和風險?

答案: 有風險,js的基本資料型別有 String Number Boolean undefined null和一種複雜資料型別object(ES6新增了symbol)。

對於複雜資料型別object,其實typeof null返回的也是object,因為本質上null就是一個佔位用的物件。另一方面,陣列Array也不能用typeof檢測資料型別,因為同樣會返回object

因此,如果想要檢測bar是不是object,可以這樣子:

    console.log((bar !== null) && (tiopnuiop[yuiop[]\\]poi456/ypeof bar ==='object'))
    //當然,如果認為function也是 object,可以用下面的語句
    console.log((bar !== nul)&& (typeof bar ==='object')||(typeof bar ==='function'))
複製程式碼

除此以外,還有比如Array的情況,因為Array也會返回object,如果我們不像讓Array被認為是Object,就必須真正的認清Array,人情Array的方法有:

 console.log( bar instanceof Array)  // 如果陣列,返回true
 console.log( Array.isArray(bar))  //ES5方法
 console.log( Ojbect.prototype.toString.call(arr) === '[object Array]') 
複製程式碼
2) 以下兩個函式是否等價
function foo1()
{
  return {
      bar: "hello"
  };
}

function foo2()
{
  return
  {
      bar: "hello"
  };
}
複製程式碼

答案: 不等價!! 注意,第二個函式返回的是undefined

console.log(foo1()); // {bar : "hellp"}
console.log(foo2()); // undefined
複製程式碼

這也是為什麼函式返回物件時,或寫大括號時,把{寫在一邊,因為第二個函式js會預設return後面返回的東西(是空),等價於

return undefined
{xxx}
//後面當然,當然是寫了也白寫
複製程式碼
3) NaN是什麼?它是什麼型別?如何檢測一個變數是不是NaN

答案: NaN即Not A Number,但實際上它是Number型別 typeof NaN 將會返回Number。 這個東西比較厲害,因為

NaN === NaN  //false
複製程式碼

你會發現,它自己都不等於它自己,因此判斷變數是否是它,不能使用===。 可以使用isNaN方法

//檢查變數是否是nan
isNaN(bar);
Object.is(bar,NaN); //ES6方法,這個方法會修正JS中的一些小bug
複製程式碼

Object.is()方法,要求嚴格相等,且Object.is(NaN,NaN)會返回true

2.作用域相關問題

以下程式的輸出是什麼:

(function(){
  var a = b = 3;
})();
console.log("a defined? " + (typeof a !== 'undefined'));
console.log("b defined? " + (typeof b !== 'undefined'));
複製程式碼

答案: a defined? false
b defined? true
理解這道題的核心在於如何理解var a = b = 3這句話,實際上這句話等於

var a; 
b = 3;
複製程式碼

這樣子,實際上,b是宣告在了全域性變數中(編譯器在預編譯幫你宣告瞭,然而在嚴格模式下是不行的) a是區域性變數,所以在函式之外是沒有定義的。

3.this&物件&陣列

1)下面程式輸出是什麼
var myObject = {
    foo: "bar",
    func: function() {
        var self = this;
        console.log("outer func:  this.foo = " + this.foo);
        console.log("outer func:  self.foo = " + self.foo);
        (function() {
            console.log(this);
            console.log("inner func:  this.foo = " + this.foo);
            console.log("inner func:  self.foo = " + self.foo);
        }());
    }
};
myObject.func();


//答案
outer func: this.foo = bar
outer func: serl.foo = bar
inner func: this.foo = undefined
inner func: self.foo = bar
複製程式碼

分析: 搞清楚this的指向。記住以下幾種規則

  • 誰呼叫,this指向誰 xxx.fun()
  • new一個物件,this指向例項本身var c = new fun()
  • 使用call/apply/bind修改this指向。

看題目,outer func顯然是第一種情況,誰呼叫,this指向誰,這個時候都是myOjbect。 而在立即執行函式中,在這裡this是沒有進行繫結指向的,自然從屬於window,所以這裡this.foo是undefied

補充關於箭頭函式的this

function a() {
    return () => {
        return () => {
        	console.log(this)
        }
    }
}
console.log(a()()())
複製程式碼

注意:箭頭函式其實是沒有 this 的,這個函式中的 this 只取決於他外面的第一個不是箭頭函式的函式的 this。在這個例子中,因為呼叫 a 符合前面程式碼中的第一個情況,所以 this 是 window。並且 this 一旦繫結了上下文,就不會被任何程式碼改變。

2)陣列的filter,以下輸出結果是什麼(2018拼多多前端原題)
var arr = [1,2,3];
arr[10] = 9;
arr.filter((item)=> {
    return item === undefined?
})

//答案
[]
複製程式碼

解析: 是的,答案的確是[],不是[undefined x 7]。 首先,看下前兩句執行後,arr是什麼

console.log(arr)
//[1,2,3, emptyx7, 9]
console.log(arr[5])
//undefined
複製程式碼

從上面結果可以看出,的確中間未定義的(顯示為empty的是undefined)。那麼,filter之後,不是應該返回為undefined的資料嗎?

是的,但是,當陣列中都是undefined時,陣列就是空,或者說[empty x 7] === []

根據評論小哥哥眷你異次元的廢D,這裡對解釋進行一下更新。實際上empty和undefined是不一樣的哦。 引用自國外技術論壇的一段解釋如下:

a) It will not crash. The JavaScript engine will make array slots 3 through 9 be “empty slots.”

b) Here, a[6] will output undefined, but the slot still remains empty rather than filled with undefined. This may be an important nuance in some cases. For example, when using map(), empty slots will remain empty in map()’s output, but undefined slots will be remapped using the function passed to it:

var b = [undefined];
b[2] = 1;
console.log(b);             // (3) [undefined, empty × 1, 1]
console.log(b.map(e => 7)); // (3) [7,         empty × 1, 7]
複製程式碼

翻譯過來就是說,undefined和陣列保留的empty插槽並不是等同的,即使我們列印出相應的資料會顯示undefined,但是與js的undefined是不同的,除了arr.filter,包括arr.map()函式都是會保留empty插槽的。

4. JS小數計算不準確的bug

以下程式碼返回值是什麼

console.log(0.1 + 0.2);
console.log(0.1 + 0.2 == 0.3);

//答案: 0.30000000000000004
        false
複製程式碼

解析: 詳細的解析見連線,這裡說一下解決辦法 0.1+0.2 != 0.3

//解決辦法
parseFloat((0.1+0.2).toFixed(10));
複製程式碼

5. 演算法/思路相關

1) 討論實現判斷變數是否是整數的函式isInter(x)的實現

答案: 在ES6中,是有現成的方法Number.isInteger可以使用的。如果自己實現,思路是什麼呢

//1 異或運算
function isInter(x) {
    return x ^ 0 === x
}

//2 取整
return Math.round(x) === x  //同樣可以用floor ceil

//取餘
return (typeof x === 'number')&&(x % 1 === 0)
複製程式碼
2) 寫一個sum方法,可以實現以下兩種呼叫方式
console.log(sum(2,3)) //5
console.log(sum(2)(3)) //5
複製程式碼

答案:

//方法1
var sum = function(x,y) {
    if(y === undefined) {
        return function(y) {
            return x + y;
        }
    }else {
        return x + y;
    }
}

//方法2
var sum = function(x){
    if( arguments.length === 1) {
        return function (y) {
            return x + y;
        }
    } else {
        console.log('here');
        return arguments[0] + arguments[1];
    }
}
複製程式碼
3) 使用遞迴的方法,將obj變為obj2的格式(拼多多2018前端筆試真題)
obj = [
    {id:1,parent:null},
    {id:2,parent:1},
    {id:3,parent:2}
]

obj2 = {
    obj:{
        id: 1,
        parent: null,
        child: {
            id: 2,
            parent: 1,
            child: {
                id: ,3,
                parent: 2
            }
        }
    }
}
複製程式碼

這一題答案留給小夥伴們思考啦,因為筆者在考試時沒有寫出很漂亮的程式,就等之後整理後再貼上來,歡迎小夥伴評論區討論

相關文章