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