前端面試問題集-3

Meow Meow Picture

目錄


描述 event delegation ( 事件委派 )

https://cythilya.github.io/2015/07/08/javascript-event-delegation/


一種受惠於 Event Bubbling 而能減少監聽器數目的方法。

<div class="parent">
<div class="child" data-name="a"></div>
<div class="child" data-name="b"></div>
<div class="child" data-name="c"></div>
<div class="subitem" data-name="d"></div>
</div>
$('.parent').on('click', '.child', function(){
console.log($(this).data('name'));
});

程式碼解說

當我們 click 不同的小區塊時,就會 console 出它們個別的名字,例如:a、b 或 c。

實作方法是將 click 事件綁在 parent 上,藉由 Event Bubbling 傳遞給 child,而非直接將事件綁定在 child 上。

優點是可減少監聽器的數目,缺點是由於需要判斷哪些 child node 是我們有興趣的項目,而必須多寫一些程式碼做判斷。

在本例中,我們加上一個 filter「.child」,表示只對有「.child」這個 class 的節點有興趣,而沒有加上 「.child」的節點則不被影響,例如 click「.subitem」這個節點之後就不會 console 它的名字。

描述 this 如何在 JavaScript 中運作

https://kuro.tw/posts/2017/10/12/What-is-THIS-in-JavaScript-%E4%B8%8A/
https://blog.techbridge.cc/2019/02/23/javascript-this/


  • 脫離物件的 this 基本上沒有任何意義
  • 沒有意義的 this 會根據嚴格模式以及環境給一個預設值
  • 嚴格模式底下預設就是 undefined,非嚴格模式在瀏覽器底下預設值是 window
  • 可以用 callapplybind 改變 this 的值
  • 要看 this,就看這個函式「怎麽」被呼叫
  • 可以把 a.b.c.hello() 看成 a.b.c.hello.call(a.b.c),以此類推,就能輕鬆找出 this 的值。

描述 prototypal inheritance 如何運作

https://pjchender.blogspot.com/2016/06/javascriptprototypal-inheritance.html


透過 Object.create() 可以建立一個空物件,同時可以將你帶入 Object.create() 的參數內容變成該物件的原型。

使用 Object.create() 的方式運用繼承和原型的概念能夠非常簡便的建立物件。

AMD vs. CommonJS

AMD:
    優點:實現異步加載依賴模塊。
    缺點:開發成本高,程式碼的閱讀和撰寫比較困難。

CommonJS:
    優點:服務器端模塊重用,NPM 中模塊包多。
    缺點:加載模塊是同步的,只有加載完成後才能執行後面的操作。

null、undefined和 undeclared變數之間有什麼差異

https://cythilya.github.io/2018/10/11/types/


比較時會被轉型為 false 的值有

  • “” 空字串
  • 0, -0, NaN
  • null
  • undefined
  • false

可利用 null 會被 typeof 檢測為 object 並且會轉為 false 的結果來驗證值是否為 null。

const happy = null;

if (!happy && typeof happy === 'object') {
console.log('我是 null!');
}

未定義(undefined):
    未賦值的變數所儲存的值是 undefined,對此變數做 typeof 也會得到 undefined。

未宣告(undeclared):
    變數在未宣告並使用的狀況下會得到 ReferenceError,並指出該變數並未宣告;
    變數在未宣告並賦值的狀況下,在嚴格模式下會報錯 ReferenceError,而在非嚴格模式下,變數會成為全域變數的屬性。
    注意,對未宣告的變數做 typeof 也會得到 undefined。

總結就是,無論變數是未定義或未宣告,typeof 這兩種狀況皆會得到 undefined。

什麼是 closure, 如何/為什麼使用?

https://blog.techbridge.cc/2018/12/08/javascript-closure/
https://shubo.io/javascript-closure/
https://pjchender.blogspot.com/2017/05/javascript-closure.html


閉包是指有權訪問另一個函數作用域中變量的函數,

創建閉包的最常見的方式就是在一個函數內創建另一個函數,

通過另一個函數訪問這個函數的局部變量,

利用閉包可以突破作用鏈域,

將函數內部的變量和方法傳遞到外部。


優點之一就是能把變數隱藏在裡面讓外部存取不到,舉例來說我有個紀錄餘額的變數跟一個扣款的 function,但我有設置了一個上限,那就是最高只能扣 10 塊:

var my_balance = 999
function deduct(n) {
my_balance -= (n > 10 ? 10 : n) // 超過 10 塊只扣 10 塊
}

deduct(13) // 只被扣 10 塊
my_balance -= 999 // 還是被扣了 999 塊

儘管我們寫了 deduct 這個 function 來操作,但變數還是暴露在外部,任何人都可以直接來改這個變數。這時如果我們利用閉包來改寫,世界就不一樣了:

function getWallet() {
var my_balance = 999
return {
deduct: function(n) {
my_balance -= (n > 10 ? 10 : n) // 超過 10 塊只扣 10 塊
}
}
}

var wallet = getWallet()
wallet.deduct(13) // 只被扣 10 塊
my_balance -= 999 // Uncaught ReferenceError: my_balance is not defined

因為我把餘額這個變數給藏在 function 裡面,所以外部是存取不到的,你想要修改只能夠利用我暴露出去的 deduct 這個函式,這樣子就達到了隱藏資訊的目的,確保這個變數不會隨意地被改到。


anonymous functions 典型的使用時機

僅需執行一次的function

host objects 和 native objects 有何不同?

native objects 
    指的是原生 JavaScript 所提供的 Object 類型(Math, Date ..)

host objects 
    是指各自不同環境所另外創造的 Object 類型(document, window ..)

.call 和 .apply 有何不同?

call 與 apply 兩者皆是執行某個 function,並將這個 function 的 context(即物件)替換成第一個代入的參數。

其差異在於 call 必須將參數一一代入,而 apply 除了第一個參數代入 context 外,其餘的參數只要包在一個陣列裡面即可。

描述 Function.prototype.bind ?

每個 Function 都有一個 bind 方法,可以將某個環境丟入此方法中。
fn.bind(Person);  // 如果是 Person, 則呼叫 fn 時 this 會是 Person 環境

盡可能的詳述描述 AJAX。

簡單說 Ajax( Asynchronous JavaScript and XML) 是一種瀏覽器實作可以讓瀏覽器直接在網頁上與伺服器做溝通的一個橋梁,並且在默默作業,因此可以等待資料回來後,在運行畫面的渲染,而早期的 Ajax 寫起來非常痛苦,因為 IE 跟其他瀏覽器所支持的方式不一樣,通常都是用 XMLHttpRequest 而當時的 IE 8 所用的是 ActiveXObject 所以非常麻煩,因此當時 jQuery 所推出的 .ajax() 非常火紅,後來延伸出了 fetch 來幫助以前的困擾。

會叫做 XML 是因為當時都是用 XML 溝通,而 JSON 是後來才推出,因此也不改 API 了,就叫做 XMLHttpRequest 。

描述 JSONP 如何運作

Ajax 的核心是通過 XmlHttpRequest 獲取非本頁內容。

Jsonp 的核心則是動態添加 <script> 標籤來調用服務器提供的 js 腳本。

你有用過 JavaScript templating (樣板) ?

如果有的話,你有用過哪些 libraries? (Mustache.js, Handlebars … 等)

EJS、Jade、Pug


描述 hoisting

在 JavaScript 運行時,將變數宣告給提升,但不會影響被賦予值的時機。
// 正常
num = 6;
num = 7;
var num; // 只要有宣告就不會錯

// 無法運作
var x = 1;
console.log(x, y); // 1, undefined
var y = 2;

// 同
var x = 1;
var y;
console.log(x, y); // 1, undefined
y = 2;

描述 event bubbling

事件的觸發是由上往下找到目標後執行方法,在由下往上回到最原點,而這樣的一來一回會導致冒泡事件,如果有重疊的兩個元素,各自有方法,綁定在相同事件上時,就會導致兩個都被觸發,這是被發生在瀏覽器的事件實作,在不同瀏覽器都有可能有不同的事件觸發方式。

attribute 和 property 的不同?

Attributes
    定義在 HTML 上

Property
    定義在 DOM 上

為什麼擴展 JavaScript 內建的 objects 不是個好方法?

會導致與規格混亂,如果當這個非規格的屬性或方法被規格化後,可能會導致專案混亂與難維護。

document load event 和 document ready event 有什麼不同?

document load
    當頁面所有資源全部加載完成後(包括 DOM,css文件,js文件,圖片資源等),執行一個函數。

問題:
    如果圖片資源較多,加載時間較長,onload 後等待執行的函數需要等待較長時間,所以一些效果可能受到影響。

document ready even
    當 DOM 加載完成後執行一個函數(不包含圖片,css等)所以會比 load 較快執行。

在原生的 js 中不包括 ready() 這個方法,只有 load 方法就是 onload 事件。

== 和 === 有什麼不同?

=== 是嚴格檢查,==是鬆檢查,比較時鬆檢查會自動轉型。

參考來源

https://h5bp.org/Front-end-Developer-Interview-Questions/translations/chinese-traditional/