今天給大家分享一個JavaScript OOP中關於分辨this指向對象的小技巧,很實用呦!
我們先來看一段代碼:
大家能判斷出func();和obj.func();這兩句的this指向嗎?
首先,我們都知道的是,this的指向就是最終調用函數的對象。可是最終調用函數的對象,你能清楚地判斷出來嗎?
但是,有幾點需要注意:
① this 指向誰,不應該考慮函數在哪聲明,而應該考慮函數在哪調用!
② this 指向的永遠只可能對象,而不可能是函數。
③ this 指向的對象 ,叫做函數的上下文context,也叫函數的調用者。
什么是上下文context ?
經常看到很多資料文檔都有提到上下文,但是都不是太好理解。相信很多人犯迷糊。現在嘗試把自己的理解寫出來,也算是梳理一下。
上下文 —— 我把它理解為當前運行環境,程序運行時,程序的每條語句都有對應的上下文,即運行環境。
可以想象一下語句執行前:有個上下文對象,名稱是 context,上下文對象是window對象,即: context = window。
直接調用函數func(),此時函數體內的上下文對象就是window。
對象obj調用func函數,即:obj.func() 時,函數體內的上下文對象就是window.obj對象。
this的值,就是運行到this代碼位置時,上下文所對應的上下文對象。函數定義是並沒有運行console.log(this)語句,所以函數定義是this指向的對象還未定義,它的值是undefined,需要在函數調用時,邊解釋邊執行,執行 console.log(this) 時才分析調用函數是的上下文。最終確定this指向的值。
下面我們來看一下更多的情況,總結一下更多的規律,讓大家面對this不再糊塗:
【 接下來,我們詳細解讀一下 】
① 通過 函數名() 調用的,this永遠指向window。就是上述例子的第一個調用 func();
結果(window)
② 通過 對象.方法 調用的,this指向這個對象。就是上述例子的第二種調用方式 obj.func();
結果(obj)
③ 函數 作為數組中的一個元素存在,用數組下標調用,this指向這個數組。
結果(數組arr)
④ 函數作為 window 內置函數的回調函數使用,this指向window 。
結果(window)
⑤ 函數作為構造函數,使用new關鍵字調用,this指向新new出的對象。
結果(objs)
【區分】在HTML中新增一個div,給div添加點擊事件。
<div id="div1" style="width: 200px;height: 200px;background-color: red;" onclick="func(this)"> 這是一個div </div> <script type="text/javascript"> window.onclick = function(){ document.getElementById("div1").onclick = function(){ func(); // 最終還是使用()調用,指向Window } document.getElementById("div1").onclick = func; // 廣義對象 通過對象.方法 調用的,this指向這個對象 } function func(){ console.log(this); } </script>
規律咱們總結完了,接下來來兩個題目練練手吧!
first one:
function func(){ console.log(this); } var obj1 = { name : "obj1", arr : [func,1,{name:"obj2",func:func},3,setTimeout(func,1000)],
} // 通過對象取到數組,然后通過數組的下標調用該函數,最終指向數組。this -> obj.arr obj1.arr[0](); // obj1.arr[0]:目的是取到func,給setTimeout作為回調函數,相當於setTimeout(func,2000)。this -> window setTimeout(obj1.arr[0],2000); obj1.arr[2].func(); // 最終調用者{name:"obj2",func:func} 屬於②情況 setTimeout(obj1.arr[2].func,2000); // 最終調用者是setTimeout,同上
結果如下顯示:(調用了三次延時函數,包括一次自動調用)
second one:
var fullname = 'John Doe'; var obj = { fullname: 'Colin Ihrig', prop: { fullname: 'Aurelio De Rosa', getFullname: function() { return this.fullname; } } }; console.log(obj.prop.getFullname()); // 函數的最終調用者 obj.prop var test = obj.prop.getFullname; console.log(test()); // 函數的最終調用者 test() this-> window obj.func = obj.prop.getFullname; // 給obj追加方法 console.log(obj.func()); // 函數最終調用者是obj var arr = [obj.prop.getFullname,1,2]; arr.fullname = "TraceyW"; console.log(arr[0]()); // 函數最終調用者數組
結果如下顯示:
總結一下,this指向的規律,大家可以發現,這個規律跟函數的調用方式息息相關:
① 通過 函數名() 調用的,this永遠指向window。
② 通過 對象.方法 調用的,this指向這個對象。
③ 函數 作為數組中的一個元素存在,用數組下標調用,this指向這個數組。
④ 函數作為 Window 內置函數的回調函數使用,this指向window。 如setInterval 、 setTimeout ...
⑤ 函數作為構造函數,使用new關鍵字調用,this指向新new出的對象。
挺有用的,拿走不謝!
有需要的點關注呦~~小W會經常更新小技巧呢!如有不完善的地方,敬請拍磚!蟹蟹~~