一、變量提升
console.log(a); // undefined
var a = 10;
在JS里不同,如果先使用變量然后在定義,這種情況下會打印undefined,而不是程序報錯,這就是JS里的變量提升
var a;
console.log(a);
a = 10;
JS里會把函數和變量的聲明提升到最頂部,這樣能避免在使用的時候因為變量或者函數不存在而報錯,但是JS不會把變量的初始化賦值也進行提升,所以打印的結果是undefined而不是10
var a = 10;
function test(){
console.log(a); // undefined
var a = 20;
console.log(a); // 20
}
test();
這是一個最常見的變量提升的面試題,這個問題混淆的地方在函數外面有個變量和函數內的變量重名,函數調用之后,進入到函數test自己的作用域里,var a會提升到函數的頂部,即使重名,也會重新聲明,所以第一次打印的時候結果是undefined,接下來進行賦值,所以第二次打印結果是20,理解變量作用域能幫助理解變量提升,但是函數的提升和變量的提升,有稍微不同的地方
test();
function test(){
alert("111"); // 正常調用
}
test1();
var test1 = function(){
alert("222"); // test1不是一個函數,報錯
}
這兩種寫法區別就是第二個用一個變量接受了函數,從而提升的時候,還是var test1; 這時test1里的內容還是undefined,所以調用函數的時候會出問題,
!!!!變量提升只是把變量聲明過程進行了提升,
!!!!函數則會提升函數定義和函數體,所以變量提升更確切講應該是聲明提升
二、事件冒泡
事件冒泡是事件觸發和傳遞過程里常見問題,通過最上一層的元素觸發事件,會把事件根據結構進行傳遞,子傳父,直到傳到document,如果在這個過程里各級元素也綁定了相同的事件,事件也會觸發,比如:
<style type="text/css">
#fa{
width: 200px;
height: 200px;
background: red;
}
#ch{
width: 100px;
height: 100px;
background: blue;
}
</style>
<div id="fa">
<div id="ch">
</div>
</div>
<script type="text/javascript">
var fa = document.getElementById("fa");
var ch = document.getElementById("ch");
ch.onclick = function(){
alert("子元素點擊事件觸發");
}
fa.onclick = function(){
alert("父元素點擊事件觸發");
}
document.onclick = function(){
alert("document點擊事件觸發");
}
</script>
點擊藍色div之后三個點擊方法都會觸發,這個過程就是事件冒泡,當然了也能阻止事件的傳遞,有兩個方法,event.cancelBubble = true;和event.stopPropagation();,所以要清楚事件傳遞的順序
<div id="div1">div
<ul id="ul1">ul
<li id="li1">li
<a href="" id="a1">a</a>
</li>
</ul>
</div>
<script>
var oUl = document.getElementById('ul1'),
oLi = document.getElementById('li1'),
oA = document.getElementById('a1');
// 以下為支持w3c的瀏覽器 比如chrome firfox等
oUl.addEventListener('click',function (){
alert('ul');
},true);
oLi.addEventListener('click',function (){
alert('li');
},true);
oA.addEventListener('click',function (){
alert('a');
},true);
</script>
跟事件冒泡的順序相反的叫事件捕獲,事件先從document開始觸發,最后才觸發子元素事件,但是使用onclick這種方式沒辦法設置,只能通過addEventLinster()完成綁定,要把這個方法里的第三個參數設置成true,但是只有父元素設置成true之后,才能使捕獲.
三、事件委托
不是所有的事件冒泡都是不好的,事件委托就是通過冒泡的過程完成事件的觸發.當某個元素內有很多子元素,而且子元素都需要觸發相同的事件,可以找到子元素,然后循環綁定事件,但是這種方式雖然可以,但是效率非常低,需要把每個元素都綁定上方法,在這個時候可以使用事件委托來完成.
<ul id="ul">
<li>0001</li>
<li>0002</li>
<li>0003</li>
<li>0004</li>
</ul>
var ul1 = document.getElementById("ul1");
ul1.onmouseover = function(){
event.target.style.background = "red";
}
ul1.onmouseout = function(){
event.target.style.background = "";
}
四、面向對象
(未完待續)