結論:
一 :在一個函數上下文中,this由調用者提供,由調用函數的方式來決定。若是調用者函數,被某一個對象所擁有,那麼該函數在調用時,內部的this指向該對象。若是函數獨立調用,那麼該函數內部的this,則指向undefined。可是在非嚴格模式中,當this指向undefined時,它會被自動指向全局對象。面試
從結論中咱們能夠看出,想要準確肯定this指向,找到函數的調用者以及區分他是不是獨立調用就變得十分關鍵。segmentfault
// demo01 var a = 20; function fn() { console.log(this.a); } fn(); //fn()是調用者,爲獨立調用,非嚴格模式下指向所有對象window,所以結果爲20
// demo02 var a = 20; function fn() { function foo() { console.log(this.a); } foo(); } fn(); //fn()是調用者,爲獨立調用,非嚴格模式下指向所有對象window,所以結果爲20
// demo03 var a = 20; var obj = { a: 10, c: this.a + 20, fn: function () { return this.a; } } console.log(obj.c); // 對象obj中的c屬性使用`this.a + 20`來計算。這裏咱們須要明確的一點是,單獨的`{}`是不會造成新的做用域的,所以這裏的`this.a`,因爲並無做用域的限制,因此它仍然處於全局做用域之中。因此這裏的this實際上是指向的window對象,所以結果爲40。 console.log(obj.fn()); //fn()是調用者,他不是獨立調用,被對象obj所調用,所以它的this指向指向obj所以結果爲10
再來看一些容易理解錯誤的例子,加深一下對調用者與是否獨立運行的理解。app
var a = 20; var foo = { a: 10, getA: function () { return this.a; } } console.log(foo.getA()); // 10 var test = foo.getA; console.log(test()); // 20
foo.getA()
中,getA是調用者,他不是獨立調用,被對象foo所擁有,所以它的this指向了foo。而test()
做爲調用者,儘管他與foo.getA的引用相同,可是它是獨立調用的,所以this指向undefined,在非嚴格模式,自動轉向全局window。函數
稍微修改一下代碼,你們自行理解。this
var a = 20; function getA() { return this.a; } var foo = { a: 10, getA: getA } console.log(foo.getA()); // 10
靈機一動,再來一個。以下例子。code
function foo() { console.log(this.a) } function active(fn) { fn(); // 真實調用者,爲獨立調用 } var a = 20; var obj = { a: 10,~~~~ getA: foo } active(obj.getA); // 20
JavaScript內部提供了一種機制,讓咱們能夠自行手動設置this的指向。它們就是call與apply。全部的函數都具備着兩個方法。它們除了參數略有不一樣,其功能徹底同樣。它們的第一個參數都爲this將要指向的對象。對象
以下例子所示。fn並不是屬於對象obj的方法,可是經過call,咱們將fn內部的this綁定爲obj,所以就可使用this.a訪問obj的a屬性了。這就是call/apply的用法。繼承
function fn() { console.log(this.a); } var obj = { a: 20 } fn.call(obj); //結果爲20
箭頭函數中,沒有this。若是你在箭頭函數中使用了this,那麼該this必定就是外層的this。也正是由於箭頭函數中沒有this,所以咱們也就無從談起用call/apply/bind來改變this指向。
在ES6中,會默認採用嚴格模式,所以this也不會自動指向window對象了,而箭頭函數自己並無this,所以this就只能是undefined,這一點,在使用的時候,必定要慎重慎重再慎重,否則踩了坑你都不知道本身錯在哪!這種狀況,若是你還想用this,就不要用使用箭頭函數的寫法。ip
箭頭函數 this指向是在定義的時候處在的對象就是它的this。箭頭函數的this看外層的是否有函數,若是有,外層函數的this就是內部箭頭函數的this,若是沒有,則this是window。作用域
var a = 10; var obj = { a:99, fn1: () => { console.log(this.a)}, fn2:function () { console.log(this.a)} } obj.fn1(); //10 obj.fn2(); //99
let btn1 = document.getElementById('btn1'); let obj = { name: 'kobe', age: 39, getName: function () { btn1.onclick = () => { console.log(this);//obj }; } }; obj.getName();
上例中,因爲箭頭函數不會建立本身的this,它只會從本身的做用域鏈的上一層繼承this。
那假如上一層並不存在函數,this指向又是誰?
let btn2 = document.getElementById('btn2'); let obj = { name: 'kobe', age: 39, getName: () => { btn2.onclick = () => { console.log(this);//window }; } }; obj.getName();
上例中,雖然存在兩個箭頭函數,其實this取決於最外層的箭頭函數,因爲obj是個對象而非函數,因此this指向爲Window對象
參考文章:
全方位解讀this
你還沒搞懂this
// 修改$對象裏面的代碼,使得如下代碼運行正常 var $ = { fn:function () { console.log(1); }, fn2:function () { console.log(2); } } $.fn().fn2(); // 答案: var $ = { fn:function () { console.log(1); return this; // 返回this,能夠繼續調用函數 }, fn2:function () { console.log(2); } } $.fn().fn2();