首先寫這篇博客是爲了整理我自己有關於this關鍵字的一些基本理解,讓自己的關於this理解更深刻些,後面會把它整理的更加完善。
javascript中this一直困擾着我,一下es5中的this,一下es6中的this,有時候自己容易暈,近期自己特意去看有關this的博客和文章,進一步加深了我對this的理解。
JS中的this,
- 在function內部創建。
- 指向啓用該函數的對象。
- this不可以被賦值,但是可以被call/apply/bind改變指向。
我先把主要的兩個重要的有關定義拋出來
1. this指向函數執行時啓用該函數的對象,如果該函數沒有被任何對象啓用(綁定),this就指向window。函數在執行時,this纔會進行綁定。
2.箭頭函數中,this是指向定義時所在的對象。
一、this和構造函數
我們常常用到構造函數,而構造函數中的this指向構造函數的實例。
function User (name,age) {
this.name = name;
this.age = age;
}
User.prototype.getName = function () {
console.log(this.name);
};
var usr1 = new User ('yang',23);
user.getName(); // yang
二、this和對象
this是在執行時纔開始綁定。因此this的指向是在執行的時候,看該函數有沒有綁定對象,如果沒有綁定對象,則是this指向window。
var obj = {
name: 'zhangsan',
getName: function () {
console.log(this.name)
}
}
obj.getName();// zhangsan
很顯然,上面的getName函數在執行時,是被obj對象調用的。因此this指向的是obj對象。
下面改變下代碼的形式:
var name = "Global";
var person = {
name: "Person",
details: {
name: "Details",
print: function () {
return this.name;
}
},
print: function () {
return this.name;
}
}
person.details.print(); //?
person.print();//?
var name1 = person.details;
var name2 = person.print;
name1.print(); //?
name2();//?
這個題很經典,我們可以逐步分析下,分析前始終要記住一句話
this指向函數執行時啓用該函數的對象,如果沒有任何對象啓用該函數,this就指向window。函數在執行時,this纔會進行綁定。
person.details.print(),很明顯是被person.detail調用,返回person.details.name,即"Details"。person.print()同理和print在被person調用,返回person.name,即"Person"。
name1 = person.details,person.details 賦值給了name1,person.details的引用賦值給了name1,name1.print()也是 name1.person調用的,因此返回的結果也是"Details"。
而name2是直接被person.print函數賦值的。name2()前面沒有任何東西調用它,因此name2指向的是window。
三、this和dom/事件
示例1:
<div id="nav" onclick="alert(this)"></div>
//this指向nav
示例2:
<div id="nav" onclick="alert(this)"></div>
<script>
var nav = document.getElementById('nav');
nav.onclick= function () {
alert(this);
}
//同理this指向的是id爲nav的dom元素
</script>
示例3:
<div id="nav" onclick="getId()"></div>
<script>
function getId(){
alert(this.id);
}
</script>
可能剛開始會以爲結果爲nav.其實不然,還是原來的那句話,this的指向,是看函數執行時而非定義時,是指向函數執行時啓用該函數的對象,只要函數沒被任何對象啓用(綁定),this都指向window。
四、this和箭頭函數
箭頭函數中的this指向時在函數定義時的對象。
下面可以看一個
var obj = {
data: [1,2,3],
dataDouble: [1,2,3],
double: function () {
console.log("在doucle函數中");
console.log(this); // @1 表示第一個this
return this.data.map(function(item){
console.log(this); // @2 表示第二個this
return item*2;
});
},
doubleArrow: function () {
console.log("在doucleArrow函數中");
console.log(this);//@3 表示第三個this
return this.data.map((item) => {
console.log(this); // @4 表示第四個this
return item*2;
})
}
}
obj.double();
obj.doubleArrow();
obj.double(),是被obj啓用的,所以在 @1和 @3 顯然都是指向的obj對象。可以複製代碼執行看下結果就知道了。
return this.data.map(function(item){
console.log(this); // @2 表示第二個this
return item*2;
});
this.data.map中的是匿名函數,沒用被任何對象啓用,因此@2指向的是window;
return this.data.map((item) => {
console.log(this); // @4 表示第四個this
return item*2;
})
箭頭函數就不同了,箭頭函數中的this指向定義時所在的對象,因此@4指向的是obj對象。
參考文章
http://caibaojian.com/deep-in-javascript-this.html
https://www.cnblogs.com/snandy/p/4773184.html
https://www.cnblogs.com/libin-1/p/6069031.html