avatarHannah Lin

总结

这篇文章是关于前端工程师面试中常见的 JS 观念题的解释和总结。

摘要

这篇文章是关于前端工程师面试中常见的 JS 观念题的解释和总结。作者分为五个部分来解释这些概念,包括 var、const、let;bind、call、apply;Spread Operator和Rest Parameter;Callback、Promise和async/await;Event Bubbling、Event Capturing和Event Delegation。对于每个概念,作者都提供了简要的解释和示例代码。

观点

这篇文章的观点是,面试中常见的 JS 观念题是前端工程师必须掌握的基本知识点。这些概念在实际开发中也经常被使用,因此对于前端工程师来说,理解这些概念并能够应用到实际开发中是非常重要的。

总结

这篇文章是关于前端工程师面试中常见的 JS 观念题的解释和总结。作者分为五个部分来解释这些概念,包括 var、const、let;bind、call、apply;Spread Operator和Rest Parameter;Callback、Promise和async/await;Event Bubbling、Event Capturing和Event Delegation。对于每个概念,作者都提供了简要的解释和示例代码。这些概念在实际开发中也经常被使用,因此对于前端工程师来说,理解这些概念并能够应用到实际开发中是非常重要的。

[面試] 前端工程師一定要會的 JS 觀念題-中英對照之下篇

1. 前端工程師一定要會的 JS 觀念題-中英對照之上篇 2. 前端工程師一定要會的 JS 觀念題-中英對照之下篇

🔖 文章索引
1. var, const, let
2. bind, call, apply
3. Spread Operator… / Rest Parameter…
4. Callback, Promise, async/await
5. Event Bubbling (propagation), Event Capturing, Event Delegation

這一篇會來寫面試很常被問的 What’s the difference between A and B? 題型

個人覺得這篇的考題用口語解釋其實滿難的,若面試現場有紙筆或是白板可以寫程式碼搭配口語(甚至畫一些圖?!) 會容易一些 。

另一個我喜歡的面試小技巧是化被動為主動。什麼意思? 當初在面試前我幾乎把理論題都背得滾花爛熟了,熟到幾乎不用思考就可以回答的程度。那我就在想,面試時間基本上是固定的,不如讓每一個回答都盡量能舉一反三讓面試官明白我除了 A 連 B 也懂 (例如問完 varletconst我可以接著說他們在 Hoisting 上的差異)。這樣不但能預防面試官出了我不會的題目也能夠避免對方說太多英文聽不懂的囧境 XD 。但前提是你要真的很熟相關知識,不然也很容易被面試官舉一反三問倒。

var, const, let

const means that a variable’s value never changes, so const can’t be re-assigned the value ; let is similar with var , they’re all variable declaration, but the biggest difference is var is function scope but let , const is block scope

var 是 es6 出現之前定義變數的方法。 const 是常數一宣告就要指定值而且也不能被賦值 (不可再賦值也就是不能用 = 讓他有新的位址),適合定義顏色這種不會變動的 ; letvar 相當像,最大不同就是 var 是 function scope 而 letconst 是 block scope ( function、if、for 都是 block scope)

只有在自己的 scope 裡才讀得到值

var 變數在 if loop 裡還是會暴露到 global 環境。而 constlet 因為是 block scope 所以 b 在外面是讀不到的

推薦閱讀

bind, call, apply

They allow us to borrow functions and set the this value in function invocation.

.bind allow you to execute the function in the future because it returns a new function that fixes the context this and first arguments if given.

.call and .apply will execute the function immediately. The difference are.callaccept subsequent arguments but .applyexpects the second argument to be an array

js 中 this 是動態的,所以會需要這些好方法讓函式怎麼被呼叫都能有固定的 this

.bind() 讓 function 在呼叫前先綁定某個物件,不會馬上執行。 .call().apply() 都是馬上去執行這個 function ,並將此 function 的 this 替換成第一個參數帶入的物件。他們唯一的不同是傳入參數的方法,.call() 是由「逗點」隔開,而 .apply() 則是傳入陣列作為參數。

推薦閱讀

Spread Operator… / Rest Parameter…

The spread operator is used to unpack elements from an array or an iterable object (like a string or a set) into individual elements.

the rest parameter is a feature that allows a function to accept an indefinite number of arguments

Spread Operator / Rest Parameter 雖然語法都是但他們很不一樣,Spread Operator 可以把一個陣列展開成個別的值,而 Rest parameter 收集剩下的值變成一個陣列

// Rest parameter
var argumentsLength = function(...args) {
 // 也可以把 array like args 轉 array 使用 [...args]
 return args.length
};

argumentsLength(1,2,3) // 3

// Spread Operator
let arr = [3];
let arr2 = [8, 9, 15];

let merged = [0, ...arr, 2, ...arr2];

alert(merged); // 0,3,2,8,9,15

// copy array
let arr = [1, 2, 3];
let arrCopy = [...arr]; 

推薦閱讀

延伸考題 array-like object 跟 array 有什麼不同 ?

像 function 裡的 arguments 是 array like object ,他可以使用 lengthfor…ofarguments[0] 等但卻不能使用 array 原生方法例如 pushforEach …等。若想要使用 array 原生方法必須使用 […arguments]Array.from() 轉成真正 array 才能使用

var a = function(...args){

    console.log(args)  // [['1', 2], 100, 'hannah']
    console.log(typeof(args)) // array-like object
    
    console.log(...args) // ['1', 2], 100, 'hannah'
    
    console.log([...args]) // [['1', 2], 100, 'hannah']
    console.log(typeof([...args])) // array
    
    console.log(args.toString()) // 1,2,100,hannah
    console.log(typeof(args.toString())) // string
}

a(['1', 2], 100, 'hannah')

Callback, Promise

我是會分別解釋兩者然後再說結論

https://johnpapa.net/async-comparisons/

Callback Function

A callback function is a function passed into another function as an argument, so a callback is a function will be executed after parent function is executed

用函式當作參數放進另外一個函式,透過另一個函式來呼叫它

function func1(x) { alert(x); }  
// 用 func1 當作參數傳入函式 func2
function func2(var1, callback) {     
    callback(var1);  
}
func2(2, func1);

所以 func2 一定會先被執行才會輪到 func1,再沒有 promise 概念以前其實很常頻繁使用 callback function,但也要小心太多層會導致 callback Hell

完整呈程式碼在此

Promise

The Promise object represents the eventual completion (or failure) of an asynchronous operation and allow us to work with the results. Promises have three states: pending, fulfilled or rejected.

Promises help you naturally handle errors, and write cleaner code by not having callback parameters.

Promise 是一個表示非同步運算的最終 完成 失敗 的物件。Promise 物件會有三種狀態::pending 初始狀態 、 fulfilled 表示操作成功地完成 、 rejected 表示操作失敗。如果我們需要依序串連執行多個 Promise 功能的話,可以透過 .then() 來做到。

The properties state and result are internal. We can’t directly access them. We can use the methods .then/.catch/.finally for that.
var p = new Promise(function(resolve, reject) {
    // Do an async task and then...
    if(/* good condition */) {
        resolve('Success!');
    } else {
       reject('Failure!');
    }
});

p()
  .then(() => {
      /* do something with the result */
  })
  .catch(() => {
      /* error */
  })
 .finally(() => {
    /* runs when the promise is settled, 
       doesn't matter successfully or not 
       他在 promise 發生後一開始就被觸發
    */
  })

結論

Callbacks are the standard way of handling asynchronous code in JavaScript, but promises are the best way to handle asynchronous code.

延伸考題 What’s about async?

The async function is syntactic sugar for promise.

async/await 其實是 promise 語法糖,讓你可以用更簡潔的方法達到非同步。(async function 本身就會回傳 promise)

用比較實務去 fetch API 就會如以下 (react Hook 為範例)

推薦閱讀

Event Bubbling (propagation), Event Capturing

Bubbling When an event happens on an element, it first runs the handlers on it, then on its parent, then all the way up on other ancestors. 從啟動事件的元素節點開始,逐層往上傳遞

Event Capturing the event goes down to the element. 從最上層的母元素開始,逐層往下傳遞

事件兩者都會執行 ,會先執行 Capturing 再執行 Bubbling

當然你可以提供 addEventListener 第二個參數去補抓順序

  • If it’s false (default), 會被設定為 Bubbling
  • If it’s true, 會被設定為 Capturing
var btn = document.getElementById('btn');
btn.addEventListener('click', function(){
  console.log('HELLO');
}, false ); // Bubbling

若需要取消 Bubbling 也可以使用 event.stopPropagation()

延伸考題: What’s Event Delegation?

If there are many elements inside one parent, and you want to handle events on them — don’t bind handlers to each element. Instead, bind the single handler to their parent and get the child from e.target Event Delegation是一種運用 Event Bubbling 概念而能減少監聽器數目的方法,將事件處理器綁在目標元素的父元素上進行處理,可以減少大量子事件監聽器的數量

<!-- HTML -->
<ul id="list">
    <li><a href="#">1</a></li>
    <li><a href="#">2</a></li>
    <li><a href="#">3</a></li>
    <li><a href="#">4</a></li>
    <li><a href="#">5</a></li>
</ul>

若不用 Event Delegation 你需要重覆綁 5 次 而運用 Event Delegation 你只要綁定一次就可以了。

推薦閱讀

後記

關於面試相關文章可以寫得實在太多,希望今年能再慢慢把它分享出來

Interview
Recommended from ReadMedium