關於js函數中this的指向的問題

@(javascript)[JavaScript中this的指向]javascript

關於js函數中this的指向的問題

javasript函數中this的指向一直都是許多編程入門新手的一個問題,老師把這個this的指向弄錯誤。下面咱們能夠來看看關於this指向的幾種狀況。html

不過在講以前,請各位始終記住一句話: JavaScript中的this一直指向觸發這個事件(函數)的這個Objoct(對象)。java

第一種:函數直接添加在行內

<button onclick="alert(this.innerHTML);">this就是指向這個div盒子</button>
複製代碼

點擊看看: 此時的這個alert(this.innerHTML);事件是直接寫在button這個元素行內的。是這個button元素觸發的這個事件。編程

第二種:經過對象.事件名來實現

這是html代碼函數

<button id="box">經過js事件的點擊事件</button>
複製代碼

下面是js代碼ui

document.getElementById("box").onclcik = function(){
	alert(this.innerHTML);
}
複製代碼

this

以上的兩種方式都很好理解,也不作過多的說明。spa

第三種:函數的調用的形式

這種方式也是存在許多的變種,先來看看上面例子的一個變種。 這是html代碼code

<button id="box1">經過js事件的點擊事件</button>
複製代碼

下面是js代碼htm

document.getElementById("box1").onclick = a;
function a(){
	alert(this);
}
複製代碼

這一種形式的事件與上面的實際上是同樣的,不過是單獨定義了一個函數,而後點擊調用這個函數。

在看看下面的例子

<button id="box1">經過js事件的點擊事件</button>
複製代碼

下面是js代碼

document.getElementById("box1").onclick = function(){
	a();
}
function a(){
	alert(this);
}
複製代碼

此時的這個與上面的有很類似,不一樣的就是此時的這個a函數是在一個事件函數裏面執行的。此時的邏輯是:我點擊這個ID爲box1的button,讓後觸發事件後面的函數function(){a();}。此時呢裏面的a函數其實尚未執行。到這個函數執行的時候,執行到裏面的函數了,a函數本身調用執行(函數加括號執行),那麼問題來了,是誰調用的這個a函數呢?答案是:window。由於不存在上面說的兩種以及Object.函數的形式。這個就有點像是定義了一個函數自執行。

像這樣

function t(){
	console.log(this);
}
/** * 此時的這個 t 函數是由誰調用的呢(也就是鼠標哪個對象讓他執行的?) * 答案是的 null * 而在 js 中,若是 this 的指向是null會自動轉換爲 window */
t();
複製代碼

或者是這樣:

function t(){
	function t2(){
		console.log(this);
	}
	t2()
}
t();
複製代碼

OK!接下來看看這個:

function intro(){
	console.log('名字是'+ this.name,this );
}
var dog = {name: "狗"};
dog.intro = intro;
dog.intro(); // 狗
複製代碼

分析一下:此時先定義了一個名字是intro的一個函數,在定義一個dog對象並賦值name=狗。下面的代碼就是在dog這個對象上添加一個intro對象,賦值爲一開始定義的那個函數intro。此時的這個dog對象就多了一個屬性intro,值是函數。接着在調用這個dog.intro();。那麼是誰調用的呢?很明顯是這個dog對象調用的這個函數。因此此時的這個this就是指向dog對象。那this.name就是了。

OK!再來:

function intro(){
	console.log('名字是'+ this.name,this );
}
var dog = {name: "狗"};
dog.intro = intro;
dog.intro(); // 狗

var cat = {name:"貓"};
cat.intro = dog.intro;
cat.intro(); // 貓
複製代碼

如今多了一個cat,看這句cat.intro = dog.intro;。這個是把dog下面的intro方法賦值給了cat下面新建的一個intro方法。此時涉及到一個內存的問題。js中的對象,函數等都是存放在內存中,給其餘對象賦值爲這個函數的時候就是讓這個對象的這個屬性指向內存中的這個函數,因此,無論上面的是怎樣賦值,catdogintro的值是指向同一個函數的。不一樣的是調用他們的對象不一樣,致使this不一樣,因此最後的this.name的值不一樣。

再來看看這個呢?

function intro(){
	console.log('名字是'+ this.name,this );
}
var dog = {name: "狗"};
dog.intro = intro;
dog.intro(); // 狗

var cat = {name:"貓"};
cat.intro = dog.intro;
cat.intro(); // 貓

(cat.intro = dog.intro)(); // 空 this 指向window```javascript
function intro(){
	console.log('名字是'+ this.name,this );
}
var dog = {name: "狗"};
dog.intro = intro;
dog.intro(); // 狗

var cat = {name:"貓"};
cat.intro = dog.intro;
cat.intro(); // 貓

(cat.intro = dog.intro)(); // 空 this 指向window
複製代碼

此時的在上面的就是多了一句(cat.intro = dog.intro)();。那爲何就指向window了呢? 上面的這個例子,涉及到的是關於計算機裏面的計算,cat.intro = dog.intro 這是一個賦值運算,而賦值運算的結果是 = 右側的值,此時這個值並不屬於任何一個對象,而這個值是一個空,也能夠說是一個 null ,因此此是爲 null 轉爲指向 window。能夠這麼作一個比喻:

一天張三去麪館吃麪,給老闆說:「老闆,一碗牛肉麪」,作好面後,此時的這碗牛肉麪這個就有了。至關於上面的intro函數,此時呢他並不屬於張三。當老闆把這碗麪端到張三面前,這是才屬於張三。OK。李四也去吃麪,進入麪館,看見張三的面。對老闆說:「老闆,來一碗和他同樣的面」。此時老闆須要計算,這碗麪是什麼面?至關於上面的cat.intro = dog.intro計算。老闆計算後才知道這碗麪是牛肉麪。此時讓一個加括號執行,那確定就不行了。此時的這碗麪並不屬於李四。賦值的結果是是什麼呢?當老闆把這碗麪端到李四面前,這是才屬於李四。這就是結果。

須要注意的點就是cat.intro = dog.intro只是一個賦值過程,值是=右邊的東西。執行cat.intro = dog.intro會致使一個結果就是cat下面多了一個intro屬性而且有值。

基本普通的函數中的this存在的問題就是這麼多,其餘的也就是上面的一些變種。

不過,能夠發現,由於this指向window的存在,會致使污染全局,因此多數時候使用構造函數new的方式更可取,這樣this纔不會指向全局避免污染全局。

上面說了這麼多。其實也就是最開始說的那句: JavaScript中的this一直指向觸發這個事件(函數)的這個Objoct(對象)。

相關文章
相關標籤/搜索