摘要:過去的幾年,我看過很多人對(duì)方法的調(diào)用滿是迷惑。事實(shí)上,這也是說明的作用。這就是方法調(diào)用的本質(zhì)。簡(jiǎn)單的方法調(diào)用顯然用調(diào)用方法非常的麻煩。注意上面的規(guī)則同樣適用于的方法調(diào)用。成員方法下一個(gè)常遇到的調(diào)用方法的情況是調(diào)用一個(gè)對(duì)象的方法。
過去的幾年,我看過很多人對(duì)javascript方法的調(diào)用滿是迷惑。尤其是對(duì)方法里的this的語(yǔ)義抱怨頗多。
在我(作者)看來,只要弄清楚了方法的本質(zhì),上面的以后自然清晰。事實(shí)上,這也是ECMAScript說明的作用。在某種意義上這篇文章是說明文檔的簡(jiǎn)寫版,但是核心內(nèi)容是一致的。
核心本質(zhì)首先,我們方法調(diào)用的本質(zhì)是一個(gè)方法的call方法[1]。它是如下運(yùn)作的。
創(chuàng)建一個(gè)參數(shù)列表(argList),包含了從頭到尾的全部參數(shù)
第一個(gè)參數(shù)是thisValue
調(diào)動(dòng)方法。把this作為thisValue,argList作為參數(shù)列表。
比如:
function hello(thing) { console.log(this + " says hello " + thing); } hello.call("Yehuda", "world"); // => Yehuda says hello world
就如所看到的,我們調(diào)用了hello方法,this的值是Yehuda而一個(gè)多帶帶的參數(shù)是"world"。這就是javascript方法調(diào)用的本質(zhì)。你可以把所有其他的方法調(diào)用都看做是方便版。
簡(jiǎn)單的方法調(diào)用顯然用call調(diào)用方法非常的麻煩。Javascript允許我們這樣調(diào)用方法:hello("world")。當(dāng)我們這樣調(diào)用的時(shí)候?qū)嶋H上是這樣的:
function hello(thing) { console.log("Hello " + thing); } // this; hello("world"); // 等于 hello.call(window, "world");
這個(gè)行為會(huì)在使用strick mode[2]的時(shí)候發(fā)生改變:
// this: hello("world"); // 等于 hello.call(undefined, "world");
上面的例子簡(jiǎn)單來說就是:一個(gè)方法的調(diào)用,比如:fn(...args)其實(shí)和fn.call(window[ES5-strict: undefined], ...args)。
注意:上面的規(guī)則同樣適用于inline的方法調(diào)用。(function(){})()和(function() {}).call(window [ES5-strict:undefined])。
成員方法下一個(gè)常遇到的調(diào)用方法的情況是調(diào)用一個(gè)對(duì)象的方法(person.hello())。在這個(gè)情況下,調(diào)用的順序是:
var person = { name: "Brendan Eich", hello: function(thing) { console.log(this + " says hello " + thing); } }; // this person.hello("world"); //等于 person.hello.call(person, "world");
注意:其實(shí)hello方法是如何綁定到對(duì)象上的。記住我們之前是如何把hello方法定義為一個(gè)多帶帶的方法的。我們來看看如果方法是動(dòng)態(tài)綁定到對(duì)象上的會(huì)發(fā)生什么:
function hello(thing) { console.log(this + " says hello " + thing); } person = {name: "Brendan Eich}; person.hello = hello; person.hello("world"); //等于person.hello.call(person, "hello"); hello("world"); // "[object DOMWindow]world"
注意方法里的this并不是一成不變的。它總是在被調(diào)用的時(shí)候被賦值。
使用Function.prototype.bind如果this的值可以保持不變的話,那就方便多了。一個(gè)常用的方法就是使用閉包來讓一個(gè)方法的this不再改變:
var person = { name: "Brenda Eich", hello: function(thing) { console.log(this.name + " says hello " + thing); } } var boundHello = function(thing) {return person.hello.call(person, thing);} boundHello("world");
雖然我們的boundHello的調(diào)用的本質(zhì)還是boundHello.call(window, "world"),我們來看看bind是如何運(yùn)作的:
var bind = function(func, thisValue) { return function() { return func.apply(thisValue, aguments); } } var boundHello = bind(person.hello, person); boundHello("world"); // "Brendan Eich says hello world"
為了理解上面的例子,你只需要知道兩個(gè)事實(shí)。一、arguments是一個(gè)類似于數(shù)組的對(duì)象,它代表了全部傳入方法的參數(shù)。二、apply方法和call方法本質(zhì)上是一樣的,只不過類數(shù)組的參數(shù)代替了逐個(gè)列出的參數(shù)。
我們的bind方法只是返回了一個(gè)新的方法。當(dāng)它被調(diào)用的時(shí)候,我們的新方法調(diào)用了傳入的方法,設(shè)置了this的值。同時(shí)其他的參數(shù)也傳入進(jìn)來。
因?yàn)檫@個(gè)基本上就是一個(gè)非常通用的模型。ES5給所有的Function都引入了一個(gè)新的bind。這個(gè)bind是這樣工作的:
var boundHello = person.hello.bind(person); boundHello("world");
這個(gè)在你想把一個(gè)方法作為回調(diào)傳入的時(shí)候非常有用:
var person = { name: "Alex Russell", hello: function() { console.log(this.name + " says hello world"); } } $("#some-div").click(person.hello.bind(person)); // 當(dāng)div被點(diǎn)擊的時(shí)候,"Alex Russell says hello world"就會(huì)出現(xiàn)
這確實(shí)顯得很笨拙,TC39(指定新的ECMAScript標(biāo)準(zhǔn)的組織)還在制定更加優(yōu)雅的,向后兼容的方法。
關(guān)于jQuery因?yàn)閖Query用了非常的多的匿名方法,它內(nèi)部調(diào)用了call方法來設(shè)置回調(diào)的this值。比如,所有回調(diào)都被用call方法設(shè)置了當(dāng)前的元素為this值,而不是用window作為this的值。
這一點(diǎn)非常有用,因?yàn)槟涿椒ㄗ鳛榛卣{(diào)并不是特別有用,但是它會(huì)給剛接觸Javascript的人一種this非常奇怪的印象:總之就是經(jīng)常改變,難以推斷。
如果你能把一個(gè)方法的調(diào)用順其自然的理解為func.call(thisValue, ...args)的調(diào)用方式,那就可以輕而易舉的理解Javascript里this的值了。
原文鏈接:http://yehudakatz.com/2011/08...
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/85128.html
摘要:的關(guān)鍵字總是讓人捉摸不透,關(guān)鍵字代表函數(shù)運(yùn)行時(shí),自動(dòng)生成的一個(gè)內(nèi)部對(duì)象,只能在函數(shù)內(nèi)部使用,因?yàn)楹瘮?shù)的調(diào)用場(chǎng)景不同,的指向也不同。其實(shí)只要理解語(yǔ)言的特性就很好理解。個(gè)人對(duì)中的關(guān)鍵字的理解如上,如有不正,望指正,謝謝。 javascript的this關(guān)鍵字總是讓人捉摸不透,this關(guān)鍵字代表函數(shù)運(yùn)行時(shí),自動(dòng)生成的一個(gè)內(nèi)部對(duì)象,只能在函數(shù)內(nèi)部使用,因?yàn)楹瘮?shù)的調(diào)用場(chǎng)景不同,this的指向也不...
摘要:原文許多人被中的關(guān)鍵字給困擾住了,我想混亂的根源來自人們理所當(dāng)然地認(rèn)為中的應(yīng)該像中的或中的一樣工作。盡管有點(diǎn)難理解,但它的原理并不神秘。在瀏覽器中,全局對(duì)象是對(duì)象。運(yùn)算符創(chuàng)建一個(gè)新對(duì)象并且設(shè)置函數(shù)中的指向調(diào)用函數(shù)的新對(duì)象。 原文:Understanding the this keyword in JavaScript 許多人被JavaScript中的this關(guān)鍵字給困擾住了,我想混亂的...
摘要:理解文章中已經(jīng)比較全面的分析了在中的指向問題,用一句話來總結(jié)就是的指向一定是在執(zhí)行時(shí)決定的,指向被調(diào)用函數(shù)的對(duì)象。與和直接執(zhí)行原函數(shù)不同的是,返回的是一個(gè)新函數(shù)。這個(gè)新函數(shù)包裹了原函數(shù),并且綁定了的指向?yàn)閭魅氲摹? 理解 JavaScript this 文章中已經(jīng)比較全面的分析了 this 在 JavaScript 中的指向問題,用一句話來總結(jié)就是:this 的指向一定是在執(zhí)行時(shí)決定的,...
摘要:在中,當(dāng)使用關(guān)鍵字調(diào)用函數(shù)構(gòu)造函數(shù)時(shí),函數(shù)構(gòu)造函數(shù)中也有這個(gè)概念,但是它不是惟一的規(guī)則,而且常??梢砸脕碜圆煌瑘?zhí)行上下文的不同對(duì)象。因此,我們使用調(diào)用函數(shù),可以看到這是對(duì)象,并且的屬性是正常的。 一直以來,javascript里邊的this都是一個(gè)很難理解的東西,之前看的最多的就是阮一峰老師關(guān)于this的理解: http://www.ruanyifeng.com/blo... htt...
摘要:基本操作理解寫在前面在面向?qū)ο蟮恼Z(yǔ)言中,關(guān)鍵字的含義是明確且具體的,即指代當(dāng)前對(duì)象。一般在編譯期確定下來,或稱為編譯期綁定。全局范圍內(nèi)當(dāng)在全部范圍內(nèi)使用,它將會(huì)指向全局對(duì)象。輸出瀏覽器中運(yùn)行的腳本,這個(gè)全局對(duì)象是。 js基本操作-this理解 寫在前面 在面向?qū)ο蟮恼Z(yǔ)言中,this關(guān)鍵字的含義是明確且具體的,即指代當(dāng)前對(duì)象。一般在編譯期確定下來,或稱為編譯期綁定。而在 JavaScr...
閱讀 1361·2021-09-24 10:26
閱讀 3678·2021-09-06 15:02
閱讀 632·2019-08-30 14:18
閱讀 588·2019-08-30 12:44
閱讀 3128·2019-08-30 10:48
閱讀 1952·2019-08-29 13:09
閱讀 2006·2019-08-29 11:30
閱讀 2292·2019-08-26 13:36