1. 程式人生 > 其它 >JavaScript中子函式訪問外部變數的方法

JavaScript中子函式訪問外部變數的方法

我們在寫web頁面時,肯定會經常遇到下面這種情況:

<body>
  
<div class="btns-wrapper"></div>
  
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
var wrapper = $('.btns-wrapper');
for(var i = 0; i < 5; i++){
	var btn = $('<button>按鈕' + i + '</button>').appendTo(wrapper);
	btn.on('click', function(evt){
		console.log('點選按鈕:' + i);
	});
}
</script>
  
</body>

程式碼很簡單,就是在頁面上建立幾個按鈕,同時定義按鈕的點選事件

可當點選按鈕時,我們發現獲取到的序號一直都是5,也就是 i 最後的值。

這是因為定義click事件時的匿名函式所引用的都是同一個變數 i

解決辦法1:立即執行

var wrapper = $('.btns-wrapper');
for(var i = 0; i < 5; i++){
	var btn = $('<button>按鈕' + i + '</button>').appendTo(wrapper);

	//預設方法
	//btn.on('click', function(evt){
	//	console.log('點選按鈕:' + i);
	//});

	//方法1:立即執行
	btn.on('click', (function(n){
		return function(evt){
			console.log('點選按鈕:' + n);
		}
	})(i));

}

這種方式就是在定義事件時直接為每個按鈕都建立了一個獨立的匿名函式(閉包),並且每個函式都持有正確的 i 變數

解決辦法2:利用jquery的事件傳參

var wrapper = $('.btns-wrapper');
for(var i = 0; i < 5; i++){
	var btn = $('<button>按鈕' + i + '</button>').appendTo(wrapper);

	//預設方法
	//btn.on('click', function(evt){
	//	console.log('點選按鈕:' + i);
	//});

	//方法2:利用JQuery的事件傳參
	btn.on('click', { i: i }, function(evt){
		console.log('點選按鈕:' + evt.data.i);
	});

}

這種辦法就簡單多了,直接利用jquery將引數體傳遞給匿名函式即可。

解決辦法3:利用dom的data屬性

var wrapper = $('.btns-wrapper');
for(var i = 0; i < 5; i++){
	var btn = $('<button>按鈕' + i + '</button>').appendTo(wrapper);

	//預設方法
	//btn.on('click', function(evt){
	//	console.log('點選按鈕:' + i);
	//});

	//方法3:利用dom的data屬性
	btn.data('i', i);
	btn.on('click', function(evt){
		console.log('點選按鈕:' + $(this).data('i'));
	});

}

這種方法也很簡單,弊端就是無法利用data屬性定義結構化的資料。

綜合來看,如果是jquery環境,利用事件引數來轉遞變數是最簡單的,而且可以傳遞結構化的資料。

否則只能通過立即執行(閉包)的方式。