我們在開發一些大型前端項目時,會遇到這樣一種情況,某個變量上有個字段。我們想知道是哪一段程式修改了這個變量上的字段。比如全局變量window上我們自定義了一個新字段_name,我們想知道到底有哪些程式給這個字段賦了值。
一行行地調試肯定太費時間了。如果window這個變量的_name字段被程式指派時,能執行我們自己實作的一個監聽器,這樣不就友善多了麼?
監聽器的實作很簡單:
</div><div data-lake-id="8aefc718ff7602389583fab9aade7025">"use strict";</div><div data-lake-id="6bc14f8648e1582f2ecf3f155977988b">function test(){</div><div data-lake-id="57cd4f2c445497acde5a09157a0155ab"> Object.defineProperty(window, "_name", {</div><div data-lake-id="aab407ce1995e0baeab6263846a07546"> get : function(){ console.log("gett is called ") },</div><div data-lake-id="0c7168109822bebe2ee4af50bcbf8e80"> set : function(newValue){</div><div data-lake-id="34e6a305616c936d81e63014fa49a814"> debugger;</div><div data-lake-id="af61554705fdc7460a1abd9fee557cd6"> console.log("_name is filled!!!!");</div><div data-lake-id="cb763f581769d8a49dffc84966155fdb"> },</div><div data-lake-id="19b1ea7d93a669b1a5513b750458bf9d"> enumerable : true,</div><div data-lake-id="65607326fa8a534ed2ca7e02d57986cb"> configurable : true</div><div data-lake-id="1511cedf5b95c0b1627c1258f107ece8">});</div><div data-lake-id="98eb4b3f8f229e32eeaf1377e55e9abf">for( var i = 0; i < 2; i++)</div><div data-lake-id="61f271edd8c8e0b46d838965579b3a64"> console.log(i);</div><div data-lake-id="4d57f5375fc2259bf295d17d0b5c232a">window._name = "2";</div><div data-lake-id="c8ce63356472283cad62913339dfb2b5">};</div><div data-lake-id="9f01be8628cc3990ce8c677d14583bc1">test();</div><div data-lake-id="a1ae02a4e286202ddd3a0241ca812c91">
使用Object對象自帶的方法defineProperty, 第一個參數為要監聽的對象window,第二個參數為要監聽的對象字段名稱,_name。
第三個參數是一個對象,屬性為set,意思是我們想監聽window._name被指派的這個事件。屬性set的值為一個JavaScript函數,即我們自己定義的監聽器。這個監聽器,當window._name被其他JavaScript函數修改之後,就會觸發。
測試一下,在浏覽器裡執行上述代碼,發現斷點按照我們期望的被觸發了:
從調用棧也能發現确實是window._name = “2”這一行代碼觸發的斷點,我們自己注冊的屬性修改監聽器确實工作了。