this
的第一次接觸是做一個父容器事件代理的DEMO,當時還不會jquery;
<ul class="ct">
<li>內容1</li>
<li>內容2</li>
<li>內容3</li>
</ul>
var ct=document.querySelector('.ct');
ct.addEventListener('click',function(e){
console.log(e.target.innerText);
});
第一次接觸this
,感覺這個太厲害了,就是誰調用就是誰;后來遇到這樣一個DEMO
function foo(){
console.log(this);
function foo2(){
console.log(this);
}
foo2();
}
foo();
我以為第一個結果是window
,第二個結果是foo2
,結果控制臺的輸入狠狠的打臉了!
輸出結果
當時我就懵逼了,因為從"元素之力"的世界來,"零一世界"的運作原理還知之甚少,后來經過別人點撥,這個是由于堆棧,是計算機的一個原理;
后來我想想,應該是我在全局環境下調用了foo(),然后window將整個foo()給推入了堆棧,第一個輸出為window理所應當,那么foo(2)也是被window給推進堆棧的,"幕后黑手"也是window,這樣應該就解釋了,這個demo中第二個輸出的結果還是window,雖然是函數內部嵌套函數,但this依舊指向了window;
手賤的我又看到了call和apply,這種切換this的手段
var obj1 = {
name:'ran',
fn:function(){
console.log(this);
}
};
obj1.fn();
var fn2 = obj1.fn;
fn2();
fn2.call(obj1);
為什么會這樣呢?
- 第一個:obj.fn()是obj去調用fn的,當然第一個是他,這個沒有什么異議;
- 第二個陷阱就來了,在全局環境下聲明fn2=obj.fn;再去執行fn2,這個時候相當于再全局環境下執行
function(){
console.log(this);
}
一開始,我也犯了迷糊,明明fn在obj之內,怎么又指向全局了,后來我想明白了,這只是一個賦值,讓fn2擁有這個函數罷了,相當于obj是一個銀行,fn就是100快,現在銀行外面的fn2從銀行取出一個100快,總不能因為都是100快,就說fn2的錢還是銀行的吧;
- 第三個:用call切換了,函數的作用域,打到了切換this的指向,本來fn2的作用域是全局,this是指向window的,結果被call切換到了obj里面,自然把黑鍋又給了obj,那么這個this就指向了obj,最后輸出也是obj,而不是window;