this對象的涵義就是指向當前對象中的屬性和方法。(所以關(guān)鍵在于當前對象是什么)。this總是與調(diào)用位置有關(guān),與聲明位置無關(guān)。即誰調(diào)用這個函數(shù)或方法,this關(guān)鍵字就指向誰。
擴展:javascript是詞法作用域 / 靜態(tài)作用域(就是說這個標識符寫在哪里,就只能在哪里用)。
以下我們通過一些例子來有關(guān)this關(guān)鍵字的一些用法。
-
瀏覽器中,當調(diào)用方法沒有明確的指向時,默認指向window。
node中,頂級作用域module.exports,指向global;但在node-cli下與瀏覽器一致。
舉個栗子:
var obj = {
name:'a',
foo:function(){
console.log(this.name)
}
}
var obj2 = {
name:'b',
foo:obj.foo
}
obj.foo(); //a
obj2.foo(); //b
var obj3 = {
name:'b',
foo:function(){
var testfoo = obj.foo;
testfoo();
}
}
obj3.foo(); //undifined,這時this指向window ,因為testfoo并沒有一個明確的對象調(diào)用它
-
在瀏覽器中setTimeout,setInterval和匿名函數(shù)執(zhí)行時的當前對象是window
// 栗子3
var name = 'b';
var obj = {
name:'c',
showname:function(){
console.log(this.name)
},
foo:function(){
(function(cb){
cb();
})(this.showname)//立即執(zhí)行函數(shù),此時this的指向是window
}
}
obj.foo();
-
eval 等同于在聲明位置填入代碼。所以該函數(shù)執(zhí)行時的作用域是當前作用域。
// 栗子4 eval
var name = 'a';
var obj = {
name:'c',
showName:function(){
eval(console.log(this.name)); //其實等同于直接console.log(this.name)
}
}
obj.showName(); //c
-
apply,call
提到this關(guān)鍵字不得不提apply,call ,它們能強制改變函數(shù)執(zhí)行時的對象,即可以改變this指向。
// 栗子5 apply
var name = 'b';
var obj = {
name:'c',
showname:function(){
console.log(this.name)
}
}
var obj2 = {
name:'d'
}
obj.showname.apply();
obj.showname.apply(null);
obj.showname.apply(undifined); //b,指向window
obj.showname.apply(obj2); //d
call與apply作用是一樣的,也是改變this指向。不同之處在于傳參形式。如下:
function test(a, b) {
console.log(a + b);
}
test.apply(null, [1, 2]); //3
test.call(null, 1, 2); //3
//第一個參數(shù)是指定函數(shù)內(nèi)部中this的指向,這里指向全局
-
bind
提到call與apply,這里還需要提一下bind,它有個特性 柯里化(將多個參數(shù)的函數(shù)變成只帶一個參數(shù)的函數(shù))。
舉個栗子:
var sum = function(x,y) {
return x + y
};
var succ = sum.bind(null, 1); //讓this指向null,其后的實參也會作為實參傳入被綁定的函數(shù)sum
succ(2) // => 3: 1已經(jīng)綁定到了sum函數(shù)中的x
call和apply模擬實現(xiàn)bind
Function.prototype.bind = function(context) {
var _this = this, args = Array.prototype.slice.call(arguments);
return function() {
return _this.apply(context, args.slice(1));
}
};
-
es6箭頭函數(shù)
因為javascript的this很古怪,所以從es6出現(xiàn)了箭頭函數(shù),它在聲明時綁定this,通過babel轉(zhuǎn)化。
var name = 'a';
var obj = {
name:'b',
showName:()=>{
console.log(this.name)
}
}
obj.showName(); //a ,this指向window