一直對Javascript中的this都有一種似是而非的感覺,今天突然感覺豁然開朗,特此記錄一下。
咱們先看個栗子:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>this的使用</title> <script type="text/javascript"> var Car,tesla; Car=function () { this.start=function(){ console.log('car started'); }; this.turnKye=function () { var carKey=document.getElementById('car_key'); carKey.onclick=function () { this.start(); }; } return this; } tesla=new Car(); tesla.turnKye(); </script> </head> <body> <input type="button" id="car_key" value="test" /> </body> </html>
咋一看這段代碼沒有什麼問題,但是由於對於this的錯誤理解最終導致錯誤的結果。我們在元素car_key上面綁定了click事件,認為在car的類中嵌套綁定click事件就可以讓這個dom元素訪問car的this上下文。這種方式看起來很合理,但是不幸的是它並不工作。
在Javascript中,this關鍵字總是指向正執行的作用域的所有者。
請大家仔細揣摩上面那句話。正如我們所知,函數調用會產生新的作用域,一點onclick事件被觸發,this就指向了dom元素而不是Car的類。
那我們怎麼做才會讓它能正常工作呢?我們通常會把this賦值給一個局部的自由變量(比如that,_this,self,me等,這個在許多的框架裡面都有體現)來避開作用域帶來的問題。這裡使用局部變量來重寫之前的方法:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>this的使用</title> </head> <body> <input type="button" id="car_key" value="test" /> <script type="text/javascript"> var Car,tesla; Car=function () { this.start=function(){ console.log('car started'); }; this.turnKye=function () { var that=this; var carKey=document.getElementById('car_key'); carKey.onclick=function () { that.start(); }; } return this; } tesla=new Car(); tesla.turnKye(); </script> </body> </html>
由於that是一個自由變量,onclick事件的出發並不會引起它的重新定義。
如果你熟悉ES6的話可以使用胖箭頭符號,這更簡潔和更容易理解,如下:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>this的使用</title> </head> <body> <input type="button" id="car_key" value="test" /> <script type="text/javascript"> var Car,tesla; Car=function () { this.start=function(){ console.log('car started'); }; this.turnKye=function () { //var that=this; var carKey=document.getElementById('car_key'); //carKey.onclick=function () { // that.start(); //}; carKey.onclick=()=>this.start(); } return this; } tesla=new Car(); tesla.turnKye(); </script> </body> </html>
當然我們也可以使用綁定函數的方法來解決這個問題:如下
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>this的使用</title> </head> <body> <input type="button" id="car_key" value="test" /> <script type="text/javascript"> var Car,tesla; Car=function () { this.start=function(){ console.log('car started'); }; var click=function(){ this.start(); } this.turnKye=function () { //var that=this; var carKey=document.getElementById('car_key'); carKey.onclick=click.bind(this); } return this; } tesla=new Car(); tesla.turnKye(); </script> </body> </html>
其實這些在學習React的時候,綁定事件的時候遇到的坑,那時候只知道這麼寫,不知道怎麼回事,今天突然感覺豁然開朗。希望對大家有所幫助。