# 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

## 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, "柴油");
```