[JaveScript] this 的細節
一般函式的 this
console.log(this);
global
browser: window
function a(){
console.log(this);
}
a(); // 結果 window
四種情況
- 直接執行 -> global (window)
- 作為物件的成員函式執行 -> 該物件
- 作為 DOM 的事件偵聽函式 -> 該 DOM
- 作為建構函式 -> 建構出來的實例
const obj = {
name: 'object',
a(){
console.log(this);
},
};
obj.a();
// 結果是 物件本身
const b = obj.a;
b();
// 結果是 window
<button id="btn">btn</button>
function a(){
console.log(this);
};
btn.addEventListener('click', a);
// 結果是 DOM 本身
function A(){
console.log(this);
};
const x = new A();
// 結果是 new 出來的物件
題目:
function a(){
console.log(this); // 結果是 obj
};
const obj = {};
obj.a = a;
obj.a();
const obj = {
a(){
console.log(this); // 結果是 obj
function b(){
console.log(this); // 結果是 window, 因為是直接執行
}
b();
}
}
obj.a();
function a(){
console.log(this); // 結果是 btn
}
const obj = {a};
btn.addEventListener('click', obj.a());
function a(){
console.log(this); // 結果是 window
}
const obj = {
b(){
return function (){
console.log(this); // 結果是 btn, obj.b()(函式) 執行以後, 裡面的 this 就是 btn
a();
}
}
};
btn.addEventListener('click', obj.b());
function a(){
console.log(this); // 結果是 btn
}
const obj = {
a(){
return a;
}
}
btn.addEventListener('click', obj.a());
function MyClass(){
}
const x = new MyClass;
x.addEventListener('loaded', function()
console.log(this); // 如果 x 不為 DOM, 結果不一定, 要看 class 怎麼寫的
})
箭頭函式的 this 永遠等於他外面的 this
const a = () => {
console.log(this); // 結果是 window
}
const obj = {
a: ()=>{
console.log(this); // 結果是 window
}
}
btn.addEventListener('click', a);
obj.a();
function a(){
// console.log(this);
const b = ()=>{
console.log(this); // 結果是 btn
}
b();
}
btn.addEventListener('click', a);
vue 組件的 this 使用箭頭函式要先確定裡面沒有使用到 this, 否則結果可能不如預期
<div id="app">
<button
@click="test"
>
btn
</button>
</div>
const vm = new Vue({
el: '#app',
computed:{
value(){
console.log(this); // 結果是 vm 這個實例(組件)
}
}
methods:{
test(){
console.log(this); // 結果是 vm 這個實例(組件)
},
},
watch:{
value(){
console.log(this); // 結果是 vm 這個實例(組件)
}
}
});
bind/apply/call 的 this
一般函式 bind: 把函式的 this 綁定到物件上,產生新的函式
<button id="btn">btn</button>
function a(){
console.log(this);
}
const obj = {};
const b = a.bind(obj);
btn.addEventListener('click', b); // 結果是 {}
apply:
<button id="btn">btn</button>
function add(){
console.log(this);
console.log(x + y);
}
add(3,5); // 結果 window 與 8
add.apply(0, [3, 5]); // 結果 numbwe{0} 與 8
add.apply(btn, [3, 5]); // 結果 btn 與 8
/*
apply(context, [array]);
context 要綁定的東西, 同 bind()。傳入的是什麼 this 就會變成傳入的那個
*/
call: 與 apply 很像,差別在後面的參數 不限數量 (不是陣列)
<button id="btn">btn</button>
function add(){
console.log(this);
console.log(x + y);
}
add(3,5); // 結果 window 與 8
add.call(0, 3, 5); // 結果 numbwe{0} 與 8
add.call(btn, 3, 5); // 結果 btn 與 8
箭頭函式
const add = (x, y) => {
console.log(this);
console.log(x + y);
}
const b = add.bind(btn); // 結果 window 與 8
b(3, 5);
add.apply(btn, [3, 5]); // 結果 window 與 8
add.call(btn, 3, 5); // 結果 window 與 8
/*
bind、apply、call 對箭頭函式是無效的
*/
Q&A
1.
Vue
new Vue( {
el:"#app",
methods: {
test: () => this // 是 window
},
} )
// 小括號是函式,大括號是物件
Jquery + Vue
function init() {
new Vue({
el:"#app",
methods: {
test: () => this // 是 window
},
})
}
document.addEventListener("ready", init); // 結果是 document
$(document).ready(init); // 不一定,要看他函式怎麼寫
Mylib.ready(init); // 不一定,要看他函式怎麼寫
2.
// 取得被點擊 menu 的 id,顯示被點擊的 context
<span data-id='1' class="menu">A</span>
<span data-id='2' class="menu">B</span>
<span data-id='3' class="menu">C</span>
<br>
<span data-id='3' class="context">AA</span>
<span data-id='3' class="context">BB</span>
<span data-id='3' class="context">CC</span>
$('.menu').click(function(){
const id = $(this).data('id');
console.log(id);
$('.context').hide();
$('.context[data-id="${id}"]').show();
})
3.
Vue 處理 SEO
1. pre-render -- 適用於動態內容不多
2. Server side rendering (SSR) -- 適用於動態內容多
ps: 箭頭函式不能作為建構式