首先,要知道的是
this
是指函數當前的運行環境(上下文)。javascript
咱們都知道 this 是函數運行時所在的環境,但咱們不知道是函數的運行環境究竟是怎麼決定的。java
var obj = {
fn:function(){
console.log(this.title);
},
title:"Hello"
}
var fn = obj.fn;
var title = "Hi";
obj.fn() //"Hello"
fn() //"Hi"
複製代碼
上面的例子中,obj.fn
和 fn
調用的都是同一個函數,但結果卻不同,這就是咱們上面說的 this 是根據運行時所在環境不一樣致使的,對於 obj.fn
來講,fn
是運行來 obj
環境的,因此this
指向 obj
,對於 fn
來講是運行在全局的,所以 this
指向的是全局,也就是 window
。數據結構
那爲何 obj.fn()
就是在 obj
環境運行的,而一旦 var fn = obj.fn
就變成全局環境了呢?下面讓咱們一點點揭開 this
的神祕面紗。閉包
javascript 之全部有 this,是和內存結構有關係的。app
var obj = {fn:5}
複製代碼
以上代碼,將一個對象賦值給變量 obj
,在 javascript
的 引擎中會先在內存中,生成一個對象 { fn:5}
,而後在將這個對象的地址賦給變量 obj
。函數
就是說,變量 obj
只是存了一個地址,若是要進行取讀操做 obj.fn
,那引擎是先從 obj
拿到內存地址,而後在從該地址讀出原始對象,而後返回它的 fn 屬性。ui
原始的對象以相似於字典結構的狀態保存,每個屬性名都對應一個屬性描述對象。拿上面的那個例子的 fn
屬性來看this
注意!fn 屬性的值是保存在屬性描述對象的 value 屬性裏面spa
屬性值不是一個函數的時候很清晰,那若是屬性的值是一個函數呢?3d
var obj = { fn: function(){}};
複製代碼
當對象的屬性值是函數的時候,javascript
引擎會單獨把函數保存在內存中,而後再將函數的地址賦值給 fn
屬性的屬性描述對象的 value
屬性上。
因爲函數是單獨的一個值,因此它能夠在不一樣的環境 ( 上下文 ) 中運行。
var fn = function(){
console.log(this.age);
};
var obj = {
fn: fn,
age: 5
};
var age = 10;
//單獨運行時
fn(); //10
//在obj中運行時
obj.fn(); // 5
複製代碼
因爲 javascript 容許函數體內,引用當前環境的其餘變量,而變量是有當前的運行環境提供的,那麼因爲函數是能夠在不一樣的運行環境中執行,那就須要一種機制,一種可以在函數體內部得到當前運行環境。so,這時 this 出現了,它的目的就是在函數體內部,指向函數當前的運行環境。
function fn (){
console.log(age); //由運行環境提供
}
var age= 10";
fn(); //10
複製代碼
以上代碼中的 age 就由該函數運行時所在的環境提供。
再看,下面的例子
function fn(){
console.log(this.xx);
}
var xx = 10;
var obj = {
fn: fn,
xx: 100
}
//單獨運行時
fn()//10
//在obj中運行時
obj.fn()//100
複製代碼
this.xx
指向運行時所在的環境的 xx。fn()
單獨運行時,this.xx
指向全局環境的 xx。obj.fn()
運行時,則 this.xx
指向的是 obj
環境的 xx。如今,咱們回到文章中最開始提出的問題,obj.fn()
是經過 obj
找到的 fn
,因此就是在 obj
環境執行,一旦 var fn = obj.fn
,則 變量 fn
就直接指向了函數自己,因此 fn()
就變成了全局環境執行。
注意!不要忘記,當對象裏的屬性名的值是一個函數的時候,這時,javascript 引擎就報函數單獨保存在內存中,而後把函數地址給了 屬性名的屬性描述對象的value上。
this 是 javascript 中的一個關鍵字。
它是在運行時,在函數體內自動生成的一個對象,所以只能在函數體內使用
下面讓咱們直截了當的來看下 this 的幾種使用方式
函數的一般用法,這種屬於全局調用,所以這時 this
就表明者全局對象
var x = 1;
function fn(){
console.log(x); // 變量 x,這時是全局的變量 x
}
fn(); //1
複製代碼
匿名函數執行時,this
表明者全局
var x = 1;
var fn = function(){
console.log(this.x);
}
fn(); // 1
//經常使用閉包式匿名函數
(function(){
console.log(this.x)
})() //1
複製代碼
當函數做爲對象調用的時候,此時的 this
是這個上級對象
function fn(){
console.log(this.x); //this 指向 obj
}
var obj = {
x:1,
m:fn
}
obj.m(); // 1
複製代碼
當經過構造函數,生成一個新對象時,此時 this
是指這個新對象
function Fn(){
this.x = 1;
}
var x = 2;
var obj = new Fn();
obj.x // 1
複製代碼
apply/call
是函數的一個方法,主要就是用來改爲函數調用的,第一個參數就是要改變的對象,所以,this 就是指這第一個參數,若是第一個參數無,那 this
就表明者全局
var x = 1;
function fn(){
console.log(this.x);
}
var obj = {
x: 2,
m:fn
}
obj.m.apply(); // 1
複製代碼
更多詳情請移步 阮一峯老師博文