摘要:雖然方法定義在對(duì)象里面,但是使用方法后,將方法里面的指向了。本文都是在非嚴(yán)格模式下的情況。在構(gòu)造函數(shù)內(nèi)部的內(nèi)的回調(diào)函數(shù),始終指向?qū)嵗膶?duì)象,并獲取實(shí)例化對(duì)象的的屬性每這個(gè)屬性的值都會(huì)增加。否則最后在后執(zhí)行函數(shù)執(zhí)行后輸出的是
本篇文章主要針對(duì)搞不清this指向的的同學(xué)們!不定期更新文章都是我學(xué)習(xí)過程中積累下的經(jīng)驗(yàn),還請(qǐng)大家多多關(guān)注我的文章以幫助更多的同學(xué),不對(duì)的地方還望留言支持改進(jìn)!
首先,必須搞清楚在JS里面,函數(shù)的幾種調(diào)用方式:
1.普通函數(shù)調(diào)用
2.作為方法來調(diào)用
3.作為構(gòu)造函數(shù)來調(diào)用
4.使用apply/call方法來調(diào)用
5.Function.prototype.bind方法
6.es6箭頭函數(shù)
要點(diǎn):不管函數(shù)以何種方式來調(diào)用,誰調(diào)用這個(gè)函數(shù)或方法,this關(guān)鍵字就指向誰,牢記這一點(diǎn)。!important
下面我將對(duì)每個(gè)方法進(jìn)行實(shí)例講解!
1.普通函數(shù)調(diào)用(function fun(){ this.name="segmentfault"; console.log(this); //window console.log(this.name); //segmentfault })() console.log(window.name); //segmentfault 由此可見name屬性屬于window的屬性。
在這段代碼中fun函數(shù)作為普通函數(shù)調(diào)用,實(shí)際上fun是作為全局對(duì)象window的一個(gè)方法來進(jìn)行調(diào)用的(這點(diǎn)大家應(yīng)該都知道),即window.fun();所以這個(gè)地方是window對(duì)象調(diào)用了fun方法,那么fun函數(shù)當(dāng)中的this即指window,同時(shí)window還擁有了另外一個(gè)屬性name,值為segmentfault.
2.作為方法來調(diào)用var name="segmentfault";
var fun={
name:"segmentfault-A", showName:function(){ console.log(this.name); //輸出 segmentfault-A }
}
fun.showName();
//這里是fun對(duì)象調(diào)用showName方法,很顯然this關(guān)鍵字是指向fun對(duì)象的,所以會(huì)輸出name
var funA = fun.showName;
funA(); //輸出 segmentfault
//這里將fun.showName方法賦給funA變量,此時(shí)funA變量相當(dāng)于window對(duì)象的一個(gè)屬性,因此showNameA()執(zhí)行的時(shí)候相當(dāng)于window.funA(),即window對(duì)象調(diào)用funA這個(gè)方法,所以this關(guān)鍵字指向window
換種方式看看:
var funA={ name:"segmentfault", showName:function(){ console.log(this.name); } } var funB={ name:"segmentfault-A", sayName:funA.showName } funB.sayName(); //輸出 segmentfault-A //雖然showName方法是在funA這個(gè)對(duì)象中定義,但是調(diào)用的時(shí)候卻是在funB這個(gè)對(duì)象中調(diào)用,因此this對(duì)象指向funB3.作為構(gòu)造函數(shù)來調(diào)用
function fun(name){ this.name=name; } var funA = fun("segmentfault"); console.log(funA.name); // 輸出 undefined console.log(window.name);//輸出 segmentfault //上面代碼沒有進(jìn)行new操作,相當(dāng)于window對(duì)象調(diào)用fun("segmentfault")方法,那么this指向window對(duì)象,并進(jìn)行賦值操作window.name="segmentfault". var funB=new fun("segmentfault"); console.log(funB.name);// 輸出 segmentfault4.call/apply方法的調(diào)用
在JS里函數(shù)也是對(duì)象,因此函數(shù)也有方法。從Function.prototype上繼承到Function.prototype.call/Function.prototype.apply方法
call/apply方法最大的作用就是能改變this關(guān)鍵字的指向.
Obj.method.apply(AnotherObj,arguments);
var name="segmentfault-A"; var fun={ name:"segmentfault", showName:function(){ console.log(this.name); } } fun.showName.call(); //輸出 "segmentfault-A" //這里call方法里面的第一個(gè)參數(shù)為空,默認(rèn)指向window。 //雖然showName方法定義在fun對(duì)象里面,但是使用call方法后,將showName方法里面的this指向了window。因此最后會(huì)輸出"segmentfault-A"; function FruitA(n1,n2){ this.n1=n1; this.n2=n2; this.change=function(x,y){ this.n1=x; this.n2=y; } } var fruitA = new FruitA("cheery","banana"); var FruitB={ n1:"apple", n2:"orange" }; fruitA.change.call(FruitB,"pear","peach"); console.log(FruitB.n1); //輸出 pear console.log(FruitB.n2);// 輸出 peach
FruitB調(diào)用fruitA的change方法,將fruitA中的this綁定到對(duì)象FruitB上。
5.Function.prototype.bind()方法var name="segmentfault-A"; function fun(name){ this.name=name; this.sayName=function(){ setTimeout(function(){ console.log("my name is "+this.name); },50) } } var funA = new fun("segmentfault"); funA.sayName() //輸出 “my name is segmentfault-A”; //這里的setTimeout()定時(shí)函數(shù),相當(dāng)于window.setTimeout(),由window這個(gè)全局對(duì)象對(duì)調(diào)用,因此this的指向?yàn)閣indow, 則this.name則為segmentfault-A
下面用bind()方法就可以輸出segmentfault
var name="segmentfault"; function fun(name){ this.name=name; this.sayName=function(){ setTimeout(function(){ console.log("my name is "+this.name); }.bind(this),50) //注意這個(gè)地方使用的bind()方法,綁定setTimeout里面的匿名函數(shù)的this一直指向fun對(duì)象 } } var funA = new fun("segmentfault"); funA.sayName() //輸出 “my name is segmentfault”; //這里的setTimeout()定時(shí)函數(shù),相當(dāng)于window.setTimeout(),由window這個(gè)全局對(duì)象對(duì)調(diào)用,因此this的指向?yàn)閣indow, 則this.name則為segmentfault
這里setTimeout(function(){console.log(this.name)}.bind(this),50);,匿名函數(shù)使用bind(this)方法后創(chuàng)建了新的函數(shù),這個(gè)新的函數(shù)不管在什么地方執(zhí)行,this都指向的fun,而非window,因此最后的輸出為"my name is segmentfault"而不是"my name is segmentfault-A"
另外幾個(gè)需要注意的地方:
setTimeout/setInterval/匿名函數(shù)執(zhí)行的時(shí)候,this默認(rèn)指向window對(duì)象,除非手動(dòng)改變this的指向。在《javascript高級(jí)程序設(shè)計(jì)》當(dāng)中,寫到:“超時(shí)調(diào)用的代碼(setTimeout)都是在全局作用域中執(zhí)行的,因此函數(shù)中的this的值,在非嚴(yán)格模式下是指向window對(duì)象,在嚴(yán)格模式下是指向undefined”。本文都是在非嚴(yán)格模式下的情況。
該函數(shù)執(zhí)行的時(shí)候,this綁定到當(dāng)前作用域的對(duì)象上
var name="segmentfault-A"; var fun = { name:"segmentfault", showName:function(){ eval("console.log(this.name)"); } } fun.showName(); //輸出 "segmentfault" var a = fun.showName; a(); //輸出 "segmentfault-A"7.箭頭函數(shù)
es6里面this指向固定化,始終指向外部對(duì)象,因?yàn)榧^函數(shù)沒有this,因此它自身不能進(jìn)行new實(shí)例化,同時(shí)也不能使用call, apply, bind等方法來改變this的指向。
function Timer() { this.seconds = 0; setInterval( () => this.seconds ++, 1000); } var timer = new Timer(); setTimeout( () => console.log(timer.seconds), 3000); // 3 // 在構(gòu)造函數(shù)內(nèi)部的setInterval()內(nèi)的回調(diào)函數(shù),this始終指向?qū)嵗膶?duì)象,并獲取實(shí)例化對(duì)象的seconds的屬性,每1s這個(gè)屬性的值都會(huì)增加1。否則最后在3s后執(zhí)行setTimeOut()函數(shù)執(zhí)行后輸出的是0
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/108297.html
摘要:一前言關(guān)鍵字是中最復(fù)雜的機(jī)制之一。對(duì)于那些沒有投入時(shí)間學(xué)習(xí)機(jī)制的開發(fā)者來說,的指向一直是一件非常令人困惑的事。隨著函數(shù)使用場(chǎng)合的不同,的值會(huì)發(fā)生變化。還可以傳值,在嚴(yán)格模式下和非嚴(yán)格模式下,得到值不一樣。 一、前言 this關(guān)鍵字是JavaScript中最復(fù)雜的機(jī)制之一。它是一個(gè)很特別的關(guān)鍵字,被自動(dòng)定義在所有函數(shù)的作用域中。對(duì)于那些沒有投入時(shí)間學(xué)習(xí)this機(jī)制的JavaScript開...
摘要:一前言關(guān)鍵字是中最復(fù)雜的機(jī)制之一。對(duì)于那些沒有投入時(shí)間學(xué)習(xí)機(jī)制的開發(fā)者來說,的指向一直是一件非常令人困惑的事。隨著函數(shù)使用場(chǎng)合的不同,的值會(huì)發(fā)生變化。還可以傳值,在嚴(yán)格模式下和非嚴(yán)格模式下,得到值不一樣。 一、前言 this關(guān)鍵字是JavaScript中最復(fù)雜的機(jī)制之一。它是一個(gè)很特別的關(guān)鍵字,被自動(dòng)定義在所有函數(shù)的作用域中。對(duì)于那些沒有投入時(shí)間學(xué)習(xí)this機(jī)制的JavaScript開...
摘要:有能力對(duì)元胞狀態(tài)添加或者刪除信息,這種能力通過一種叫門的結(jié)構(gòu)來控制。一個(gè)有個(gè)這種門,來保護(hù)和控制元胞狀態(tài)。輸出將會(huì)基于目前的元胞狀態(tài),并且會(huì)加入一些過濾。同時(shí)也將元胞狀態(tài)和隱狀態(tài)合并,同時(shí)引入其他的一些變化。 循環(huán)神經(jīng)網(wǎng)絡(luò)(RNN)人們的每次思考并不都是從零開始的。比如說你在閱讀這篇文章時(shí),你基于對(duì)前面的文字的理解來理解你目前閱讀到的文字,而不是每讀到一個(gè)文字時(shí),都拋棄掉前面的思考,從頭開始...
摘要:但是有一個(gè)總的原則,那就是指的是,調(diào)用函數(shù)的那個(gè)對(duì)象作為函數(shù)調(diào)用在函數(shù)被直接調(diào)用時(shí)綁定到全局對(duì)象。這一過程分為三步創(chuàng)建類的實(shí)例。這步是把一個(gè)空的對(duì)象的屬性設(shè)置為。函數(shù)被傳入?yún)?shù)并調(diào)用,關(guān)鍵字被設(shè)定為該實(shí)例。 this 的值到底是什么?一次說清楚你怎么還沒搞懂 this?this、apply、call、bind 一、Whats this? 由于運(yùn)行期綁定的特性,JavaScript 中的...
閱讀 2475·2021-11-17 09:33
閱讀 762·2021-11-04 16:13
閱讀 1334·2021-10-14 09:50
閱讀 697·2019-08-30 15:53
閱讀 3664·2019-08-30 14:18
閱讀 3271·2019-08-30 14:14
閱讀 2100·2019-08-30 12:46
閱讀 3185·2019-08-26 14:05