套路一:事件代理
1、事件代理基本原理
事件代理的基本原理簡單來說就是將子元素的事件通過冒泡的形式交由父元素來執行。
事件冒泡:當一個子元素的事件(如click)被觸發的時候,該事件會從子元素開始向上傳播,觸發父級元素的點擊事件。
2、事件代理的應用場景
很多商品放在一個ul下面的li標簽里面,點擊添加或刪除商品,就可以綁定商品的父元素ul標簽,通過事件代理去找到要點擊的商品,完成添加刪除事件。
????????可以大量節省內存占用,減少事件注冊,例如ul上代理所有的li事件;可以實現當新增子對象時候,無需再進行事件綁定,對于動態內容尤其合適。
? ? var oUl1 = document.getElementById('ul1');
? ? myAddEvent(oUl1,'click',function(e){
? ? ? ? var e = e || window.event;
? ? ? ? var target = e.target || e.srcElement;
? ? ? ? if(target.nodeName === 'LI'){
? ? ? ? ? ? alert(target.innerHTML);
? ? ? ? ? ? target.style.background = 'red';
? ? ? ? }
? ? });
? ? // 事件綁定封裝成js函數
? ? function myAddEvent(obj, ev, fn){
? ? ? ? if(obj.attachEvent){ // ie
? ? ? ? ? ? obj.attachEvent('on'+ev, fn);
? ? ? ? }else{
? ? ? ? ? ? obj.addEventListener(ev, fn, false);
? ? ? ? }
? ? }
3、事件代理與普通事件綁定的優劣
事件代理的優點:
不需要為每一個元素都添加監聽事件而是通過代理給父元素進行處理,這樣就減少了內存,性能提高了;可以動態添加元素,不需要再給新添加的元素重新綁定事件。
事件代理的缺點:
事件代理的常用場景僅限上述情景,如果把所有事件都用事件代理,可能會出現本不該被觸發的元素被綁定上了事件。
套路二:this
在Javascript中this總是指向調用它所在方法的對象。因為this是在函數運行時,自動生成的一個內部對象,只能在函數內部使用。
1、全局的函數調用
對于全局的方法調用,this指向的是全局對象window,即調用方法所在的對象。
var name = "global this";
? ? function globalTest() {
? ? ? ? this.name = "rename global this"
? ? ? ? console.log(this.name);
? ? }
? ? globalTest(); //rename global this
????? ? 2、對象方法的調用
如果函數作為對象的方法調用,this指向的是這個上級對象,即調用方法的對象。 在以下代碼中,this指向的是obj對象。
function showName() {
? ? ? ? console.log(this.name);
? ? }
? ? var obj = {};
? ? obj.name = "ooo";
? ? obj.show = showName;
? ? obj.show(); //ooo
????? ? 3、構造函數的調用
????????構造函數中的this指向新創建的對象本身。
var name = "global name";
? ? function showName() {
? ? ? ? this.name = "showName function";
? ? }
? ? var obj = new showName();
? ? console.log(obj.name); //showName function
? ? console.log(name); //global name
????????通過new關鍵字創建一個對象的實例,new關鍵字可以改變this的指向,將這個this指向對象obj。再增加一個全局的name,用以證明this指向的不是global,在構造函數的內部,對this.name進行賦值,但并沒有改變全局變量name。
4、apply和call調用時的this
apply和call都是為了改變函數體內部的this指向。this的指向在call和apply中是一致的,只不過是調用參數的形式不一樣。call是一個一個調用參數,而apply是調用一個數組。
var value = "Global value";
? ? function FunA() {
? ? ? ? this.value = "AAA";
? ? }
? ? function FunB() {
? ? ? ? console.log(this.value);
? ? }
? ? FunB(); //Global value 因為是在全局中調用的FunB(),this.value指向全局的value
? ? FunB.call(window); //Global value,this指向window對象,因此this.value指向全局的value
? ? FunB.call(new FunA()); //AAA, this指向參數new FunA(),即FunA對象
? ? FunB.apply(window); //Global value
? ? FunB.apply(new FunA()); //AAA
套路三、原型
????? ? 在JavaScript中,萬物皆對象,但是對象也有區別,大致分為兩類,即:普通對象object和函數對象function。一般而言,通過new Function產生的對象是函數對象,其他對象都是普通對象。
function clone(obj) {
? //實現
? function Noop(){};
? Noop.prototype = obj;
? return new Noop;
};
var a ={name:"aaa"};
var b = clone(a);
console.log(b);? ? //"aaa"
a.name = "aaa1"
console.log(b.name)? //"aaa1"
b.name="bbb"
console.log(a.name)? ? //"aaa1"
a.name="aaa2"
console.log(b.name)? ? // "bbb"
原型鏈是一種機制,JavaScript中每個對象都有一個內置的proto屬性指向創建它的函數對象的原型對象,即prototype屬性。原型鏈的存在,主要是為了實現對象的繼承。原型鏈的組成包括下面幾個部分。
套路四:異步
存在三個接口,用戶,上線的電影,用戶預訂的電影,標準的解法如下,適合個人開發使用:
????????更通用的解法如下,該方法適合團隊開發協作時使用:
????????還有一種寫法如下: