say1: function() { console.log(this.value); // value
say() // 1
}, say2: function() { console.log(this.value); // value
var value = 2
say() // 1
} }
say() // 1
obj.say1()
obj.say2()
無論怎麼呼叫 say 這個 function,印出來的 value 永遠都會是全域變數的 value ,因為 say 在自己的作用域底下找不到 value 於是往上一層找,就會找到 global scope ,這跟你在哪裡呼叫 say 一點關係都沒有。 say 這個 function 在「定義」的時候就把 scope 給決定好了。
但 this 卻是完全相反,this 的值會根據你怎麼呼叫它而變得不一樣,像是先前我們剛講過的 call、apply 跟 bind ,你可以用不同的方式去呼叫 function,讓 this 的值變得不同。
// e.target refers to the clicked <li> element // This is different than e.currentTarget which would refer to the parent <ul> in this context console.log(e.target.tagName);//LI console.log(e.currentTarget.tagName);//UL
// 取得 #list ul var List = document.getElementById('list'); for (var i = 0; i < 10; i++) { // 建立 li 標籤 var node = document.createElement("LI"); // 建立 文字節點 var textnode = document.createTextNode(i); // 透過 appendChild 將 文字節點 加入至 List node.appendChild(textnode); document.getElementById("list").appendChild(node); }
輸出結果:
one
two
three
0
1
2
3
4
5
6
7
8
9
當新增或刪除一個 li 的時候,無需去處理和那個元素相關的 listener ,因為 listener 是放在 ul ,透過父節點來處理子節點的事件,就稱為事件代理。
E.CURRENTTARGET VS. E.TARGET
event.currentTarget 屬性會指向目前於冒泡或捕捉階段正在處理該事件之事件處理器所註冊的 DOM 物件,而 event.target 屬性則是會指向觸發事件的 DOM 物件。
如果放置一個 event listener 到 p 節點, event.currentTarget 就會指到 p , event.target 則還是指到 span ,如果把 event listener 放置到 body 上,則 event.currentTarget 就會指到 body :
1 2 3 4 5 6 7 8 9
<p id="list">
<a href="#">some
<span>text</span>
</a>
</p>
1 2 3 4 5 6
var list = document.getElementById('list');
list.addEventListener('click', function (e) { console.log(e.target.tagName); console.log(e.currentTarget.tagName); }, false);
<h2 class="example">A heading with class="example"</h2> <p class="example">A paragraph with class="example".</p>
<p>Click the button to add a background color all elements with class="example".</p>
<button onclick="myFunction()">Try it</button>
<p><strong>Note:</strong> The querySelectorAll() method is not supported in Internet Explorer 8 and earlier versions.</p>
<script> function myFunction() { var x, i; x = document.querySelectorAll(".example"); for (i = 0; i < x.length; i++) { x[i].style.backgroundColor = "red"; } } </script>
<p>Click the button to make changes to a list item, using the createDocumentFragment method, then appending the list item as the last child of the list.</p>
<ul id="myList"><li>Coffee</li><li>Tea</li></ul>
<script> // 取得外層容器 myList var ul = document.getElementById("myList");
// 建立一個 DocumentFragment,可以把它看作一個「虛擬的容器」 var fragment = document.createDocumentFragment();
for (var i = 0; i < 3; i++){ // 生成新的 li,加入文字後置入 fragment 中。 let li = document.createElement("li"); li.appendChild(document.createTextNode("Item " + (i+1))); fragment.appendChild(li);
}
// 最後將組合完成的 fragment 放進 ul 容器 ul.appendChild(fragment); </script>
<!-- Note that the <li> elements inside <ul> are not indented (whitespaces). If they were, the first child node of <ul> would be a text node --> <ul id="myList"> <li>Coffee</li> <li>Tea</li> <li>Milk</li> </ul>
<p>Click the button to remove the first item from the list.</p>
<button onclick="myFunction()">Try it</button>
<script> function myFunction() { var list = document.getElementById("myList"); list.removeChild(list.childNodes[0]); } </script>
<!DOCTYPE html> <html> <body> <p>Click the button to loop through the frames on this page, and change the location of every frame to "w3schools.com". </p>