---
# System prepended metadata

title: 8/28讀書會_Marco

---

# 8/28讀書會_Marco

## jQuery 的事件委托方法 on、live、delegate 之間有什麼區別？

**live**

`$('a').live('click',function() { alert("That tickles!") });`

- 主要用於給選擇到的元素上繫結特定事件型別的監聽函式
    - 利用事件委託機制，完成事件監聽處理，把節點的處理委託給document，新增元素不必再繫結一次監聽器
    - 事件冒泡到document節點的时候，檢查事件是不是 click 事件，target element能不能匹配 `a` 選擇器，如果兩個條件都是true，處理函數執行

- 缺點
    - jQuery1.7已經不推薦使用該方法，選擇器選出的元素基本算是作廢
    - event.stopPropagation()不再起作用，因為document已經全權代理所有事件
    - 如果DOM層次很深的話會影響效能


**delegate**

`$('#container').delegate('a','click',function() { alert("That tickles!") });`

- 和live類似，但不綁在document，可以自行決定要綁在哪裡 將監聽事件繫結在就近的父級元素上
    - 選擇就近的父級元素，因為事件可以更快的冒泡上去，能夠在第一時間進行處理
    - 更精確的小範圍使用事件代理，效能優於.live()。可以用在動態新增的元素上

- 優點
    - 目標元素可以指定
    - 選擇器不會預先執行
    - 適用於動態增加的元素


**on**

`$(document).on(events, selector, data, handler);`

- 將監聽事件繫結到指定元素上

- 優點
    - 使用各種事件綁定的方法統一

- 缺點
    - 會依據你要呼叫的方法不同，而有不同的綁定方式

```javascript=
// Bind
$( "#members li a" ).on( "click", function( e ) {} ); 
$( "#members li a" ).bind( "click", function( e ) {} ); 

// Live
$( document ).on( "click", "#members li a", function( e ) {} ); 
$( "#members li a" ).live( "click", function( e ) {} );

// Delegate
$( "#members" ).on( "click", "li a", function( e ) {} ); 
$( "#members" ).delegate( "li a", "click", function( e ) {} );
```


## 22. Discuss possible ways to write a function isInteger(x) that determines if x is an integer
```javascript=
// 判斷是否可以被1整除，回傳true的話就是整數
function isInteger(x) {
    return x % 1 === 0
}
```

```javascript=
// js原生方法，如果是整數會回傳true
function isInteger(x) {
    return Number.isInteger(x)
}
```

```javascript=
// 無條件捨去，若兩者相同代表是整數
function isInteger(x) {
    Math.floor(x) === x
}
```

```javascript=
// 把字串or數字轉為指定的位元數，所以轉成10進位制後，比較和原本的數字是否相同
// 相同即代表是整數
// 但在數字極大的狀況下會出錯 (save integer範圍 2的31次方-1)
function isInteger(x) {
    parseInt(x, 10) === x
}
```



## 23. In what order will the numbers 1-4 be logged to the console when the code below is executed? Why?
```javascript=
(function() {
    console.log(1); 
    setTimeout(function(){console.log(2)}, 1000); 
    setTimeout(function(){console.log(3)}, 0); 
    console.log(4);
})();
```
執行結果`1 -> 4 -> 3 -> 2`

因為console.log()是同步執行的程式碼，所以會由上到下，被放到stack中執行，而setTimeout是非同步執行函式，所以會透過web api執行，但3號因為沒有秒數，會先被推到queue中，等到stack都執行完後，才會依序呼叫queue中非同步程式碼到stack中執行



## 24. Explain how `this` works in JavaScript
- 會指向目前的執行環境(execution context)，若在瀏覽器環境會指向window，若在node.js會指向global object
- 如果是物件去呼叫的話，this會指向呼叫它的人
- 如果用箭頭函式，則無法用call, apply, bind改變this指定的對象
- 箭頭函式的this會指向**程式碼宣告時所處的環境** (lexical environment 詞彙環境)




## 25. Explain why the following doesn't work as an IIFE: `function foo(){ }();`
### What needs to be changed to properly make it an IIFE?

修改後：
`(function foo(){ })()`
`(function foo(){ }())`

因為要將程式碼分開看，`function foo(){ }`是一組function、`()`是另一組，所以要將function 包裹住在`()`中

* 需要再用小刮號包裹住，限制作用域
* IIFE執行完後，無法再被呼叫
* IIFE裡宣告的變數，只有在IIFE裏才可以用
* IIFE 最主要目的是避免污染到全域執行環境並照成污染與衝突

[Reference](https://learnwebtoday.com/javascript-interview-questions-and-answers-part-3/)
[立即函式](https://hsiangfeng.github.io/javascript/20201118/707576253/)
[IIFEs](https://pjchender.blogspot.com/2016/05/javascriptiifesimmediately-invoked.html)


## 26. What's the difference between a variable that is: null, undefined or undeclared?
### How would you go about checking for any of these states?

* null: 變數已經被宣告了，有被賦值，但是是空值
* undefined: 有被宣告但沒有被賦值，只是js先給他的名稱
* undeclared: 就是not defined，代表尚未被宣告

**確認方式**
```javascript=
// 用 ＝＝＝ 判斷
var a=null,
    b;

if (a === b) {
    console.log('same');
} else {
    console.log('different');
}

// 或者直接console.log()判斷
```


## 27. Can you describe the main difference between a forEach loop and a .map() loop and why you would pick one versus the other?

- forEach
    - 將陣列中每個元素套用到指定函式中進行運算，可以傳入三個參數
        - 第一個，表示每個元素的值
        - 第二個，表示該元素的索引值(optional)
        - 第三個，表示原本的陣列(optional)
    - 透過傳入的參數，可以修改原本陣列的值

```javascript=
let a = [1,2,3,4,5];
a.forEach((item, index, arr) => {
    arr[index] = item * 5;
});
console.log(a); // [5,10,15,20,25]
```


- map
    - 會將函式內所回傳的值，組合成一個新的陣列
    - 不會改變原有陣列、回傳的數量等於原本陣列的長度
    - 如果不回傳則是undefined

![](https://i.imgur.com/HbdbSwM.png)



## 28. How do you organize your code? (module pattern, classical inheritance?)

#### module pattern (模組模式)
[Reference](http://cythilya.blogspot.com/2015/06/javascript-module-pattern.html)

- 利用`closure`特性，將函式和變數限制在同一個範圍內存取、使用
- 避免全域污染，只在有需要的時候呼叫
- 優點
    - 清楚物件導向、封裝避免污染
- 缺點
    - 如果要變數或方法的public/private狀態，就要每個地方手動改使用方式
    - debug時候對於private members較難偵測
    - private members難以擴充、彈性不高

```javascript=
// counter只能透過incrementCounter、resetCounter取用

// function最後會return一個物件，這個物件即是公開出去的API，讓程式的其他區域可以與之互動

var testModule = (function(){
    var counter = 0;
    return {
        incrementCounter: function(){
            return counter++;
        },
        resetCounter: function(){
            console.log('counter value prior to reset: ' + counter);
            counter = 0;
        }
    };
}());

//test
testModule.incrementCounter();
testModule.resetCounter(); //counter value prior to reset: 1
```


```javascript=
var myNamespace = (function(){
    //private members
    var myPrivateVariable = 0;
    var myPrivateMethod = function(someText){
        console.log(someText);
    };
    //public members
    return {
        myPublicVariable: 'foo',
        myPublicFunction: function(bar){
            myPrivateVariable++;
            myPrivateMethod(bar);
        }
    };
}());

console.log(myNamespace.myPublicVariable); //foo
myNamespace.myPublicFunction('hi'); //hi
```


#### classical inheritance (類別繼承)
- 用在C#, JAVA，JavaScript則是`prototypal inheritance`
- 從同一個類別(class)中實例多個物件
- 可以將類別組織成層次結構，重複使用


```javascript=
// prototypal inheritance
function Car(wheel, door, fuel) {
  this.wheel = wheel,
  this.door = door,
  this.fuel = fuel
};
let truck = new Car(6, 2, "柴油");
```