javascript this 關鍵字
寫在前面
创建时间:2020-09-17 22:12:48
主要分析js中this關鍵字在不同環境中的區別
也包括function 與 ()=>中的
版本:
- node 12.9.1
- chrome 74.0.3729.157 (正式版本) (64 位元) JavaScript V8 7.4.288.28
- firfox 80.0.1 (64-bit)
參考資料
- https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/this
- https://www.runoob.com/js/js-this.html
- https://www.cnblogs.com/Nancy-wang/p/6928395.html
- https://www.php.cn/java/base/435044.html
- https://www.cnblogs.com/twoheads/p/9876396.html
正篇
何爲this
this
是面向對象編程中可以看作是對當前對象的應用,指向當前對象本身,例如在java
中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
|
public class Admin { private String adminAccount; private String password;
public Admin(String adminAccount, String password) { this.adminAccount = adminAccount; this.password = password; }
public String getAdminAccount() { return adminAccount; }
public void setAdminAccount(String adminAccount) { this.adminAccount = adminAccount; }
public String getPassword() { return password; }
public void setPassword(String password) { this.password = password; }
@Override public String toString() { return "Admin{" + "adminAccount='" + adminAccount + '\'' + '}'; } }
|
使用this關鍵字我們區分局部變量與成員變量
但是在js中this卻和java等一些面相對象變成語言有些不同
js中的this
1 2 3 4 5 6 7 8 9 10 11
| var test = function(){this.name = "name"}
this.name
test()
this.name
this
|
1 2 3 4 5 6 7 8 9 10 11
| var test = function(){this.name = "name"}
this.name
test()
this.name
this
|
1 2 3 4 5 6 7 8
| var test = function(){this.name = "name"} console.log(this.name) test() console.log(this.name) console.log(this)
|
1 2 3 4 5 6 7 8 9 10 11
| var test = function(){this.name = "name"; var a = function(){this.name = "Akeno" }; a()}
this.name
test()
this.name
this
|
通過測試我們可以看到在瀏覽器中,this
關鍵詞指的就是Window
,當然你也無法重新定義this
(至少我試了不行),無論你在哪裏使用this
都一樣都是一樣的記過
但在node中卻不是那樣,再用一個更具體的來測試一下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| var test_fun = function(){ this.value = 100; return value } console.log(test_fun()) console.log(value) console.log(this.value)
const test_obj = { value: 10, func: function() { value = 1 var a = function (){ this.value = 2 } a() return value; }, };
console.log(test_obj.func());
const test_obj = { value: 10, func: function() { value = 1 var a = function (){ this.value = 2 } a() return this.value; }, };
console.log(test_obj.func());
var f1 = function(){ return this } console.log(globalThis === f1())
|
注:js嚴格模式與非嚴格模式會有區別,我這裏是非嚴格模式
從上面的測試結果可以看出,在function
中的this
指的是函數所屬者,直接使用的話者的就是全局對象
1 2
| console.log( __dirname );
|
如果當作對象來處理呢
1 2 3 4 5 6
| var name = function () { this.name = "Akeno"; } var obj = new name(); console.log(obj.name);
|
Html中的Dom元素結果有如何呢
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| <!DOCTYPE html> <html> <head> <meta charset="utf-8"/> </head> <body> <button id="test"> click me </button> </body> <script> document.querySelector("#test").addEventListener("click", function(){ console.log(this) }) </script> </html>
|
在js的class中代碼為嚴格模式,所以this為undefined
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| class Animal { speak() { return this; } static eat() { return this; } }
let obj = new Animal(); obj.speak(); let speak = obj.speak; speak();
Animal.eat() let eat = Animal.eat; eat();
|
簡單總結
引用網上大神的總結
- 单独使用 this,它指向全局(Global)对象。瀏覽器中就是window
- 函数使用中,this 指向函数的所属者。
- 在对象方法中, this 指向调用它所在方法的对象。
- 严格模式下函数是没有绑定到 this 上,这时候 this 是 undefined。
- 在 HTML 事件句柄中,this 指向了接收事件的 HTML 元素。
- apply 和 call 允许切换函数执行的上下文环境(context),即 this 绑定的对象,可以将 this 引用到任何对象。(這個之後研究)
關於this在function與箭頭函數中
1 2 3 4 5 6 7 8 9 10 11
| var f1 = () => { return this } var f2 = function(){ return this }
console.log(f1()) console.log(f1() === this) console.log(f2()) console.log(f2() === globalThis)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| this.birth = 2030 let birth = 2010 var obj = { birth: 1990, getAge: function () { birth = 2000 var fn = function(){ birth = 2010 return new Date().getFullYear() - this.birth; } return fn(); } }; console.log(isNaN(obj.getAge()))
|
1 2 3 4 5 6 7 8 9 10 11 12 13
| var obj = { birth: 1990, getAge: function () { birth = 2000 var fn = function(){ birth = 2010 return 2020 - this.birth } return fn(); } }; console.log(obj.getAge())
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| var obj = { birth: 1900, getAge: function () { birth = 1910 var fn = function(){ birth = 1920 var fu1 = function(){ birth = 1930 return 2020 - this.birth } return fu1() } return fn(); } }; console.log(obj.getAge())
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| var obj = { birth: 1900, getAge: function (callback) { birth = 1910 var fn = function(callback){ birth = 1920 var fu1 = function(callback){ birth = 1930 return callback() } return fu1(callback) } return fn(callback) } }; console.log(obj.getAge(function(){ birth = 1940 return 2020 - this.birth }))
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| this.birth = 1800 var obj = { birth: 1900, getAge: function() { birth = 1910 var fn = function() { birth = 1920 var fu1 = () => { birth = 1930 var fu2 = () => { birth = 1940 return 2020 - this.birth } return fu2() } return fu1() } return fn(); } }; console.log(obj.getAge())
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| this.birth = 1800 var obj = { birth: 1900, getAge: () => { birth = 1910 var fn = () => { birth = 1920 var fu1 = () => { birth = 1930 var fu2 = () => { birth = 1940 return 2020 - this.birth } return fu2() } return fu1() } return fn(); } }; console.log(obj.getAge())
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| this.birth = 1800 var obj = { birth: 1900, getAge: function(){ birth = 1910 var fn = () => { birth = 1920 var fu1 = () => { birth = 1930 var fu2 = () => { birth = 1940 return 2020 - this.birth } return fu2() } return fu1() } return fn(); } }; console.log(obj.getAge())
|
通過測試我們可以發現,箭頭函數修正了function中this指向混亂的問題