this是使用常規方法調用函數時(call
)傳遞的第一個參數,它能夠在函數調用時修改,在函數沒有調用的時候,this的值是沒法肯定的。javascript
常見寫法(簡寫):java
function test(name) {
console.log(name)
console.log(this)
}
test('Jerry') //調用函數
複製代碼
完整寫法:函數
function test(name) {
console.log(name)
console.log(this)
}
test.call(undefined, 'Tom')
複製代碼
若是你傳的context 是 null 或者 undefined,那麼 window 對象就是默認的 context(嚴格模式下默認 context 是 undefined)ui
默認thisthis
const obj = {
name: 'Jerry',
greet: function() {
console.log(this.name)
}
}
obj.greet() //第一種調用方法(語法糖)
obj.greet.call(obj) //第二種調用方法
複製代碼
手動指定thisspa
const obj = {
name: 'Jerry',
greet: function() {
console.log(this.name)
}
}
obj.greet.call({name: 'Spike'}) // Spike
複製代碼
構造函數裏的this稍微有點特殊,每一個構造函數在new以後都會返回一個對象,這個對象就是this,也就是context上下文。code
function Test() {
this.name = 'Tom'
}
let p = new Test()
console.log(typeof p) // object
console.log(p.name) // Tom
複製代碼
new
關鍵字會建立一個空的對象,將this指向這個空對象,這樣的話函數內部的this就會被這個空的對象替代。對象
當this碰到return時繼承
function fn() {
this.user = 'Jerry';
return {}; // undefined
return function(){}; // undefined
return 1; // Jerry
return undefined; // Jerry
}
var a = new fn;
console.log(a.user);
複製代碼
若是返回值是一個對象,那麼this
指向的就是那個返回的對象,若是返回值不是一個對象那麼this仍是指向函數的實例。ip
function fn() {
this.user = 'Jerry';
return null;
}
var a = new fn;
console.log(a); // fn {user: "Jerry"}
複製代碼
雖然null也是對象,可是在這裏this仍是指向那個函數的實例,由於null比較特殊。
window.setTimeout()和window.setInterval()的函數中的this有些特殊,裏面的this默認是window對象。
MDN官方文檔:箭頭函數不會建立本身的this,它只會從本身的做用域鏈的上一層繼承this。
不使用箭頭函數
const obj = {
a: function() { console.log(this) }
}
obj.a() // {a: ƒ} obj對象
複製代碼
使用箭頭函數
const obj = {
a: () => {
console.log(this)
}
}
obj.a() // window
複製代碼
例子
const obj = {
a: () => {
console.log(this)
}
}
obj.a.call('123') // window
複製代碼
結合window.setTimeout()
const obj = {
a: function() {
console.log(this)
window.setTimeout(() => {
console.log(this)
}, 1000)
}
}
obj.a.call(obj) //第一個this是obj對象,第二個this仍是obj對象
複製代碼
例子1
const obj = {
a: function() { console.log(this) },
b: {
c: function() {console.log(this)}
}
}
obj.a() // obj對象, 至關於obj.a.call(obj)
obj.b.c() // obj.b對象, 至關於obj.b.c.call(obj.b)
複製代碼
例子2
const obj = {
a: function() { console.log(this) },
b: {
c: () => {console.log(this)}
}
}
obj.a() // obj對象
obj.b.c() // window!!
複製代碼
window對象就是它的上一層this,此例中的多層嵌套只是對象嵌套,這時候沒有做用域鏈
的嵌套,實際上對箭頭函數來講,仍是隻有本身一級的做用域,和上一層的window做用域
例子3
function fn0() {
return {
fn1: function () {
var obj = {
a: function() { console.log(this) },
b: {
c: () => console.log(this)
}
}
return obj;
}
}
}
fn0().fn1().b.c() // 獲得{fn1: f} fn1對象
複製代碼
在ES5中,只有全局做用域和函數做用域,並無塊級做用域,因此這裏箭頭函數仍然綁定外層this值,而非根做用域