我们在开发一些大型前端项目时,会遇到这样一种情况,某个变量上有个字段。我们想知道是哪一段程序修改了这个变量上的字段。比如全局变量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”这一行代码触发的断点,我们自己注册的属性修改监听器确实工作了。