JS中this指向
this在全局作用于下指向window
函數(shù)中使用的this指向:
- 函數(shù)在調(diào)用時未状,JavaScript會默認給this綁定一個值;
- this的綁定和定義的位置(編寫的位置)沒有關系蜕径;
- this的綁定和調(diào)用方式以及調(diào)用的位置有關系两踏;
- this是在運行時被綁定的;
this綁定方式
- 默認綁定兜喻;
- 隱式綁定梦染;
- 顯式綁定;
- new綁定
默認綁定
獨立函數(shù)調(diào)用時
獨立的函數(shù)調(diào)用我們可以理解成函數(shù)沒有被綁定到某個對象上進行調(diào)用虹统;
function foo() {
console.log(this)
}
foo() // wwindow
隱式綁定
通過某個對象進行調(diào)用的弓坞,會綁定該對象
隱式綁定有一個前提條件:
- 必須在調(diào)用的對象內(nèi)部有一個對函數(shù)的引用(比如一個屬性);
- 如果沒有這樣的引用车荔,在進行調(diào)用時渡冻,會報找不到該函數(shù)的錯誤;
- 正是通過這個引用忧便,間接的將this綁定到了這個對象上族吻;
var obj = {
name: "why",
foo: foo
}
obj.foo() // obj對象
顯式綁定
使用call和apply調(diào)用函數(shù)。
call和apply區(qū)別:第一個參數(shù)是相同的珠增,后面的參數(shù)超歌,apply為數(shù)組,call為參數(shù)列表蒂教;
這兩個函數(shù)的第一個參數(shù)都要求是一個對象巍举。在調(diào)用這個函數(shù)時,會將this綁定到這個傳入的對象上凝垛。
function sum(num1, num2, num3) {
console.log(num1 + num2 + num3, this)
}
sum.call("call", 20, 30, 40)
sum.apply("apply", [20, 30, 40])
bind顯式綁定懊悯,可以將一個函數(shù)總是顯式地綁定到一個對象上
function foo() {
console.log(this)
}
// 默認綁定和顯示綁定bind沖突: 優(yōu)先級(顯示綁定)
var newFoo = foo.bind("aaa")
newFoo()
new綁定
JavaScript中的函數(shù)可以當做一個類的構造函數(shù)來使用蜓谋,也就是使用new關鍵字。
使用new關鍵字來調(diào)用函數(shù)是炭分,會執(zhí)行如下的操作:
- 創(chuàng)建一個全新的對象桃焕;
- 這個新對象會被執(zhí)行prototype連接;
- 這個新對象會綁定到函數(shù)調(diào)用的this上(this的綁定在這個步驟完成)捧毛;
- 如果函數(shù)沒有返回其他對象观堂,表達式會返回這個新對象;
function Person(name, age) {
this.name = name
this.age = age
}
var p1 = new Person("why", 18)
console.log(p1.name, p1.age)
綁定規(guī)則優(yōu)先級
- 默認規(guī)則的優(yōu)先級最低
- 顯示綁定優(yōu)先級高于隱式綁定
- new綁定優(yōu)先級高于隱式綁定
- new綁定優(yōu)先級高于bind
- new綁定可以和bind一起使用呀忧,new綁定優(yōu)先級更高
- new綁定和call师痕、apply是不允許同時使用的,所以不存在誰的優(yōu)先級更高
其他綁定
內(nèi)置函數(shù)的綁定
setTimeout(function() {
console.log(this) // window
}, 2000)
const boxDiv = document.querySelector('.box')
boxDiv.onclick = function() {
console.log(this) // box
}
boxDiv.addEventListener('click', function() {
console.log(this) // box
})
var names = ["abc", "cba", "nba"]
names.forEach(function(item) {
console.log(this) // abcd
}, "abcd")
忽略顯示綁定
在顯示綁定中荐虐,我們傳入一個null或者undefined七兜,那么這個顯示綁定會被忽略,使用默認規(guī)則
function foo() {
console.log(this)
}
// apply/call/bind: 當傳入null/undefined時, 自動將this綁定成全局對象
foo.apply(null)
foo.apply(undefined)
間接函數(shù)引用
賦值(obj2.foo = obj1.foo)的結果是foo函數(shù)福扬;
foo函數(shù)被直接調(diào)用腕铸,那么是默認綁定;
var obj1 = {
name: "obj1",
foo: function() {
console.log(this)
}
}
var obj2 = {
name: "obj2"
};
obj2.bar = obj1.foo
obj2.bar() // obj2
(obj2.bar = obj1.foo)() // window
ES6箭頭函數(shù)this
箭頭函數(shù)并不綁定this對象铛碑,那么this引用就會從上層作用于中找到對應的this
var obj = {
data: [],
getData: function() {
setTimeout(() => {
var result = ["abc", "cba", "nba"]
this.data = result
}, 2000);
}
}
obj.getData()
const boxDiv = document.querySelector('.box')
boxDiv.onclick = function() {
console.log(obj.data) // ["abc", "cba", "nba"]
}
如果getData也是一個箭頭函數(shù)狠裹, 則不會賦值到data
var obj = {
data: [],
getData: function() {
setTimeout(() => {
var result = ["abc", "cba", "nba"]
this.data = result
}, 2000);
}
}
obj.getData()
const boxDiv = document.querySelector('.box')
boxDiv.onclick = function() {
console.log(obj.data) // []
}