js的this指向

先補充基礎知識 祕密花園  和  廖雪峯js

1.在普通模式下和嚴格模式下,this指向不同,普通模式下this指向window全局變量,而嚴格模式指向undefined

2. 下面看這道題,會輸出什麼?

var length = 10;
function fn(){
	console.log(this.length);
}

var obj = {
	length:5,
	method:function(fn){
		fn();
		arguments[0]();
	}
}

obj.method(fn,1);


在嚴格模式下,輸出10的那次的fn的this實際是undefined,在非嚴格模式下才成爲了global,並且由於JavaScript允許傳入任意個參數而不影響調用,因此傳入的參數比定義的參數多也沒有問題,雖然函數內部並不需要這些參數

至於第二的arguments[0]()的輸出,你就想一下,arguments[0]就是fn,相當於arguments['fn'](實際上只能用index來獲得,這麼寫是方便你理解),這個this是arguments.

其實綁定this的,除了顯式的bind,apply,call,就是通過object.foo或者object['foo']來綁定


3.綁定this的幾個方法,綁定this的,除了顯式的apply,bind,call(俗稱ABC方法),就是通過object.foo或者object['foo']來綁定

function foo(a, b, c) {}

var bar = {};
foo.apply(bar, [1, 2, 3]); // 數組將會被擴展,如下所示
foo.call(bar, 1, 2, 3); // 傳遞到foo的參數是:a = 1, b = 2, c = 3
bind的返回值是函數,並且

②後面的參數的使用也有區別

function f(a,b,c){
    console.log(a,b,c);
}

var f_Extend = f.bind(null,"extend_A")

f("A","B","C")  //這裏會輸出--> A B C

f_Extend("A","B","C")  //這裏會輸出--> extend_A A B

f_Extend("B","C")  //這裏會輸出--> extend_A B C

f.call(null,"extend_A") //這裏會輸出--> extend_A undefined undefined

這個區別不是很好理解

call 是 把第二個及以後的參數作爲f方法的實參傳進去,

而bind 雖說也是獲取第二個及以後的參數用於之後方法的執行,但是f_Extend中傳入的實參則是在bind中傳入參數的基礎上往後排的。


4.this 指向

* 全局範圍內,當在全部範圍內使用this,它將會指向全局對象。

* 作爲一個對象的方法調用的時候,this 指向那個對象,比如 obj.fn()
* 作爲一個普通函數(或者匿名函數)調用的時候,指向全局對象 window,比如 fn(),(這題屬於這種情況,就算你把函數定義在裏面也一樣...)
* 構造函數中 this 指向實例化的對象
* 還有使用 call 和 apply 動態改變 this 的指向


舉幾個《JavaScript 高級程序設計》上第七章的栗子...

1. 不符合預期的閉包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var name = "The Window";
 
var object = {
  name:"My Object",
 
  getNameFunc:function() {
    return function() {
      return this.name;
    };
  }
};
 
alert(object.getNameFunc()());
// The Window (非嚴格模式下),
// 此處有兩個括號,因爲 object.getNameFunc() 是一個匿名函數,
// 後一個括號是匿名函數調用。


爲什麼匿名函數沒有取得其包含作用域(或外部作用域)的 this 對象呢?

前面曾經提到過,每個函數在被調用時都會自動取得兩個特殊變量:this 和 arguments。而內部函數在搜索這兩個變量時,只會搜索到其 AO 爲止,所以永遠不能直接訪問到外部函數中的 this 和 arguments。

不過若是我們將外部作用域中的 this 對象保存在一個閉包能夠訪問到的變量裏,就可以讓閉包訪問到該對象了:

2. 符合預期的閉包
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var name = "The Window";
 
var object = {
  name:"My Object",
 
  getNameFunc:function() {
    varthat = this;
    // 使用 that 保存外部函數的 this
    //(防止被內部函數的 this 屏蔽)
 
    returnfunction() {
      returnthat.name;
      // 由於訪問的是內部 AO 中沒有的變量 that,
      // 所以在 SC 中外部的 AO 上搜索,
      // 得到外部函數的 this。
    };
  }
};
 
alert(object.getNameFunc()());// My Object


結論:在對象的方法的內部函數(可以認爲是二級函數)不會自動指向當前的對象,即就是在對象的內部函數裏面調用的函數,並不會自動繼承指向對象的this指針,而是指向window或者undefined    請看js祕密花園中的 this



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章