標籤:django data- comment lis define 作用 開始 匿名函數 ons
項目中碰到的問題,以前也碰到過,沒有重視,現記錄如下。
複製代碼<input type=‘button‘ value=‘click me‘ id=‘btn‘ /><script> var num = 0; var obj = { num: 1, fn: function() { console.log(this.num); }, init: function() { setTimeout(this.fn, 0); document.getElementById(‘btn‘).addEventListener(‘click‘, this.fn, false); } }; obj.init();</script>
輸出啥?點擊 button 後輸出啥?
解決類似的問題其實很簡單,只需要牢記下面一句話:
除了 DOM 的事件回調或者提供了執行內容(call、apply、bind)的情況,函數正常被調用(不帶new)時,裡面的 this 指向的是全域範圍。
先看第一處,其實可以改寫成這樣:
複製代碼setTimeout(function() { console.log(this.num);}, 0);
0ms後 函數正常被調用,裡面的 this 指向全域範圍 window,所以輸出即為 window.num,即為代碼最開始定義的 num=0。
再看第二處,可以改寫成這樣:
複製代碼document.getElementById(‘btn‘).addEventListener(‘click‘, function() { console.log(this.num);}, false);
click 後觸發一個回呼函數,屬於 DOM事件回調,DOM 事件回調中的 this 指向該 DOM 元素。所以輸出 this.num 即為 document.getElementById(‘btn‘).num,為 undefined。
如何能讓 click 事件後輸出 1?因為這種需求在生產中很常見,綁定各種事件,回調已經定義的對象方法。很明顯,歸根結底需要改變函數中 this 指向。
方法一:
再加一層匿名函數,使得 fn 被 obj 調用:
複製代碼var that = this;document.getElementById(‘btn‘).addEventListener(‘click‘, function() { that.fn();}, false);
方法二:
用 bind 改變 this 指向:
複製代碼// 相容IEFunction.prototype.bind = Function.prototype.bind || function(context) { var that = this; return function() { return that.apply(context, arguments); }}document.getElementById(‘btn‘).addEventListener(‘click‘, this.fn.bind(this), false);
一道經典JS題(關於this)