不管是工做或者面試中,this指向問題是常常遇到的。因此這篇文章把常見的指向問題列出來給你們,避免踩坑。首先咱們要知道,在函數中this到底取何值,是在函數真正被調用執行的時候肯定的,函數定義的時候肯定不了,也就是說,this的指向徹底取決於函數調用的位置。由於this的取值是做用域環境的一部分,每次調用函數,都會在不一樣的做用域環境。html
在瀏覽器環境嚴格模式中(區別於node),this默認指向window。當即執行函數,默認的定時器等函數,this也是指向window。node
console.log(this === window) // true function fn(){ console.log(this === window) } fn() // true (function(){ console.log(this === window) // true })() setTimeout(function() { console.log(this === window); //true }, 500)
若是函數做爲對象的一個屬性被調用時,函數中的this指向該對象。react
var x = 10 // 至關於 window.x = 10 var obj = { x: 20, f: function(){ console.log(this.x) }, s: function(){ console.log(this.x) // 20 function fn(){ console.log(this.x) } return fn // 函數f雖然是在obj.fn內部定義的,可是它仍然是一個普通的函數,this仍然指向window } } var fn = obj.f fn() // 10 obj.f() // 20 obj.s()() // 10
首先調用fn()
爲何結果爲10,由於新建了變量fn
,至關於fn = function(){ console.log(this.x)}
, 函數中this默認指向window,故輸出爲10。而 obj.f()
中this 指向obj,因此this.x = obj.x
, 輸出結果爲20。git
構造函數建立的實例的屬性指向構造函數的prototype。github
function Man(name){ this.name = name } Man.prototype.getName = function(){ // this指向 Man return this.name } const tom = new Man('tom') console.log(tom.getName()) // 'tom' // 切記請勿修改構造函數的返回值,將會改變默認指向,好比 function Man(name){ this.name = name return { name: 'lily' } } Man.prototype.getName = function(){ // this指向 Man return this.name } const tom = new Man('tom') console.log(tom.name) // 'lily'
箭頭函數的this是在定義函數時綁定的,不是在執行過程當中綁定的,箭頭函數中的this取決於該函數被建立時的做用域環境。面試
// 第一種狀況 var x= 10 var obj ={ x: 20, f1: function(){ console.log(this.x) }, f2: () => { console.log(this.x) // 指向 window } } obj.f1() // 20 obj.f2() // 10 // 第二種狀況 var name = "jack" var man = { name: 'tom', f1: function(){ // 這邊的this和下面的setTimeout函數下的this相等 var that = this setTimeout(()=>{ console.log(this.name, that === this) // 'tom' true }, 0) }, f2: function(){ // 這邊的this和下面的setTimeout函數下的this不相等 var that = this setTimeout(function(){ console.log(this.name, that === this) // 'jack' false }, 0) } } man.f1() // 'tom' true man.f2() // 'jack' false
setTimeout默認指向window,可是,在箭頭函數中,this的做用域環境在man內,故this指向了man。也就是說此時的this能夠忽略外圍包裹的setTimeout定時器函數,看上一層及的做用域。瀏覽器
特別在是react中jsx語法中,咱們一般要改變dom的this指向,否則獲取不到指定的執函數。因此一般須要在函數聲明使用bind綁定事件。dom
// html <button id="btn">myBtn</button> // js var name = 'window' var btn = document.getElementById('btn') btn.name = 'dom' var fn = function (){console.log(this.name)} btn.addEventListener('click', f()) // this指向 btn btn.addEventListener('click', f.bind(obj)) // this指向 window
本文涉及到的案例是相對比較常見,若是想更加深刻的理解this,能夠參考github上的一篇文章 ☛ 傳送門函數