JavaScript中arguments和this對(duì)象用法分析
本文實(shí)例講述了JavaScript中arguments和this對(duì)象用法。分享給大家供大家參考,具體如下:
在函數(shù)內(nèi)部有兩個(gè)特殊的對(duì)象 : arguments和this。
1、arguments對(duì)象
js函數(shù)不介意定義多少參數(shù),也不在乎傳遞進(jìn)來多少參數(shù),也就是說,即使定義的函數(shù)只接收2個(gè)參數(shù),在調(diào)用時(shí)候也未必傳遞2個(gè)參數(shù),因?yàn)閖s的函數(shù)參數(shù)在內(nèi)部使用一個(gè)數(shù)組表示的,在函數(shù)體內(nèi)可以通過arguments對(duì)象訪問此參數(shù)數(shù)組。因此,js函數(shù)可以不顯式地使用命名參數(shù)。
當(dāng)函數(shù)被調(diào)用時(shí),傳入的參數(shù)將保存在arguments類數(shù)組對(duì)象中,通過arguments可以訪問所有該函數(shù)被調(diào)用時(shí)傳遞給它的參數(shù)列表。
arguments是一個(gè)類數(shù)組對(duì)象,因?yàn)閍rguments可以通過方括號(hào)語法訪問每一個(gè)元素,且擁有一個(gè)length屬性,但它缺少所有的數(shù)組方法,因此并不是一個(gè)真正的數(shù)組。
使用arguments可以實(shí)現(xiàn)一個(gè)求和函數(shù):
function add() { var sum = 0; for (var i = 0, len = arguments.length; i < len; i++) sum += arguments[i]; return sum; }
雖然arguments的主要用途是保存函數(shù)參數(shù),但這個(gè)對(duì)象還有一個(gè)callee屬性,該屬性是一個(gè)指針,指向擁有這個(gè)arguments對(duì)象的函數(shù)。
使用arguments.callee
屬性可以實(shí)現(xiàn)一個(gè)階乘函數(shù):
function factorial(num) { if (num <= 1) return 1; else return num * arguments.callee(num - 1); }
注意:
在嚴(yán)格模式下,不能使用arguments.callee
屬性,也不能對(duì)arguments對(duì)象賦值,更不能用arguments對(duì)象跟蹤參數(shù)的變化。
可以使用命名函數(shù)表達(dá)式來達(dá)成同樣的效果:
var factorial = (function func(num) { if (num <= 1) return 1; else return num * func(num - 1); ));
由于js函數(shù)沒有簽名(定義接受的參數(shù)的類型和數(shù)量),js函數(shù)沒有重載,對(duì)于同名函數(shù),后定義的函數(shù)會(huì)覆蓋先定義的函數(shù)。當(dāng)然,通過檢查傳入的參數(shù)的類型和數(shù)量并做出不同的反應(yīng),可以模仿方法的重載。
2、this對(duì)象
與別的語言不同,JavaScript的this總是指向一個(gè)對(duì)象,而具體指向哪個(gè)對(duì)象是在運(yùn)行時(shí)基于函數(shù)的執(zhí)行環(huán)境動(dòng)態(tài)綁定的,而非函數(shù)被聲明時(shí)的環(huán)境。
- this是執(zhí)行上下文的一個(gè)屬性,其值在進(jìn)入上下文時(shí)確定,且在上下文運(yùn)行期間永久不變。
- this 是動(dòng)態(tài)綁定的,即在運(yùn)行期綁定。
- this可以是全局對(duì)象,當(dāng)前對(duì)象或任意對(duì)象,取決于函數(shù)的調(diào)用方式。函數(shù)的調(diào)用方式有以下幾種:作為普通函數(shù)調(diào)用,作為對(duì)象方法調(diào)用,作為構(gòu)造函數(shù)調(diào)用,使用
call()
和apply()
調(diào)用。
(1)作為普通函數(shù)調(diào)用
當(dāng)函數(shù)不作為對(duì)象的屬性被調(diào)用,即直接被調(diào)用時(shí),this會(huì)被綁定到全局對(duì)象。在瀏覽器的JavaScript里,該全局對(duì)象是window對(duì)象。
var name = "Alice"; function getName (name) { return this.name; } alert(getName()); // 輸出:Alice var name = "Alice"; var obj = { name: 'Bruce', getName: function(name) { return this.name; } }; var getName = obj.getName(); alert(getName()); // 輸出:Alice
以上兩個(gè)實(shí)例中,this都被綁定到了全局對(duì)象。
var firstname = "A"; var lastname = "B"; var person = { firstname : "Alice", lastname : "Bruce", setName : function(firstname, lastname) { var setFirstName = function(firstname) { this.firstname = firstname; }; var setLastName = function(lastname) { this.lastname = lastname; }; setFirstName(firstname); setLastName(lastname); } }; person.setName("Cindy", "David"); alert(firstname);//Cindy alert(lastname);//David alert(person.firstname);//Alice alert(person.lastname);//Bruce
問題:在函數(shù)內(nèi)部定義的函數(shù),this也可能會(huì)指向全局,而希望的是內(nèi)部函數(shù)的this綁定到外部函數(shù)對(duì)應(yīng)的對(duì)象上。
原因:內(nèi)部函數(shù)永遠(yuǎn)不可能直接訪問外部函數(shù)中的this變量。
解決:在外部函數(shù)體中,要進(jìn)入內(nèi)部函數(shù)時(shí),將this保存到一個(gè)變量中,再運(yùn)用該變量。
var firstname = "A"; var lastname = "B"; var person = { firstname: "Alice", lastname: "Bruce", setName: function(firstname, lastname) { var that = this; var setFirstName = function(firstname) { that.firstname= firstname; }; var setLastName = function(lastname) { that.lastname= lastname; }; setFirstName(firstname); setLastName(lastname); } }; person.setName("Cindy", "David"); alert(firstname);//A alert(lastname);//B alert(person.firstname);//Cindy alert(person.lastname);//David
(2)作為對(duì)象方法調(diào)用
當(dāng)函數(shù)作為對(duì)象方法調(diào)用時(shí),this會(huì)被綁定到當(dāng)前對(duì)象。
var firstname = "A"; var lastname = "B"; var person = { firstname : "Alice", lastname : "Bruce", setName : function(firstname, lastname) { this.firstname = this.firstname + firstname; this.lastname = this.lastname + lastname; } }; person.setName("Cindy", "David"); alert(firstname);//A alert(lastname);//B alert(person.firstname);//AliceCindy alert(person.lastname);//BruceDavid
this被綁定到了當(dāng)前對(duì)象,即person對(duì)象。
(3)作為構(gòu)造函數(shù)調(diào)用
JavaScript中沒有類,但可以從構(gòu)造器中創(chuàng)建對(duì)象,同時(shí)也提供了new運(yùn)算符,使得構(gòu)造器看起來更像一個(gè)類。
利用構(gòu)造函數(shù)創(chuàng)建新對(duì)象時(shí),可以將this來指向新創(chuàng)建的對(duì)象,避免函數(shù)中的this指向全局。
var name = "Alice"; function Person(name) { this.name = name; } var person = new Person("Bruce"); alert(name);//Alice alert(person.name);//Bruce
利用構(gòu)造函數(shù)創(chuàng)建新對(duì)象person,this指向了person。
用new調(diào)用構(gòu)造器時(shí)。還要注意一個(gè)問題,若構(gòu)造器顯式返回了一個(gè)object類型的對(duì)象,構(gòu)造器返回的結(jié)果將是這個(gè)對(duì)象,而不是this。
function Person() { this.name = "Alice" return { name: "Bruce" } } var person = new Person(); alert(person.name);//Bruce
(4)call()和apply()調(diào)用
call()
和apply()
切換函數(shù)執(zhí)行的上下文環(huán)境,即this綁定的對(duì)象;this指向的是apply()
和call()
中的第一個(gè)參數(shù)。
function Person(name) { this.name = name; this.setName = function(name) { this.name = name; } } var person1 = new Person("Alice"); var person2 = {"name": "Bruce"}; alert("person1: " + person1.name); // person1: Alice person1.setName("David"); alert("person1: " + person1.name); // person1: David alert("person2: " + person2.name); // person2: Bruce person1.setName.apply(person2, ["Cindy"]); alert("person2: " + person2.name); // person2: Cindy
apply()
將person1的方法應(yīng)用到person2上,this也被綁定到person2上。
3、this優(yōu)先級(jí)
(1)函數(shù)是否在new中調(diào)用,是的話this綁定到新創(chuàng)建的對(duì)象。
(2)函數(shù)是否通過call、apply調(diào)用,是的話this綁定到指定對(duì)象。
(3)函數(shù)是否在某個(gè)上下文對(duì)象中調(diào)用,是的話this綁定到該上下文對(duì)象。
(4)若都不是,使用默認(rèn)綁定,若在嚴(yán)格模式下,綁定到undefined,否則綁定到全局對(duì)象。
4、this丟失的問題
eg1:
var person = { name: "Alice", getName: function() { return this.name; } }; alert(person.getName()); // Alice var getName = person.getName; alert(getName()); // undefined
當(dāng)調(diào)用person.getName()
時(shí),getName()
方法是作為person對(duì)象的屬性被調(diào)用的,因此this指向person對(duì)象;
當(dāng)用另一個(gè)變量getName來引用person.getName
,并調(diào)用getName()
時(shí),是作為普通函數(shù)被調(diào)用,因此this指向全局window。
eg2:
<div id="div">正確的方式</div> <script> var getId = function(id) { return document.getElementById(id); }; alert(getId('div').innerText); </script> <div id="div">錯(cuò)誤的方式</div> <script> var getId = document.getElementById; alert(getId('div').innerText); // 拋出異常 </script>
問題:第一段調(diào)用正常,但第二段調(diào)用會(huì)拋出異常。
原因:許多引擎的document.getElementById()
方法的內(nèi)部實(shí)現(xiàn)中需要用到this,this本來期望指向的是document,當(dāng)?shù)谝欢未a在getElementById()
方法作為document對(duì)象的屬性被調(diào)用時(shí),方法內(nèi)部的this確實(shí)是指向document的,而第二段代碼中,用getId來引用document.getElementById
之后,再調(diào)用getId,此時(shí)就成了普通函數(shù)調(diào)用,函數(shù)內(nèi)部的this指向了window,而不是原來的document。
解決:利用apply把document當(dāng)作this傳入getId函數(shù),修正this。
<div id="div">修正的方式</div> <script> document.getElementById = (function(func) { return function() { return func.apply(document, arguments); }; })(document.getElementById); var getId = document.getElementById; alert(getId('div').innerText); // 拋出異常 </script>
更多關(guān)于JavaScript相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《javascript面向?qū)ο笕腴T教程》、《JavaScript常用函數(shù)技巧匯總》、《JavaScript錯(cuò)誤與調(diào)試技巧總結(jié)》、《JavaScript數(shù)據(jù)結(jié)構(gòu)與算法技巧總結(jié)》、《JavaScript遍歷算法與技巧總結(jié)》及《JavaScript數(shù)學(xué)運(yùn)算用法總結(jié)》
希望本文所述對(duì)大家JavaScript程序設(shè)計(jì)有所幫助。
相關(guān)文章
基于JS代碼實(shí)現(xiàn)當(dāng)鼠標(biāo)懸停表格上顯示這一格的全部內(nèi)容
這篇文章主要介紹了基于JS代碼實(shí)現(xiàn)當(dāng)鼠標(biāo)懸停表格上顯示這一格的全部內(nèi)容 的相關(guān)資料,需要的朋友可以參考下2016-06-06javascript實(shí)現(xiàn)的固定位置懸浮窗口實(shí)例
這篇文章主要介紹了javascript實(shí)現(xiàn)的固定位置懸浮窗口,以一個(gè)完整實(shí)例形式詳細(xì)分析了javascript實(shí)現(xiàn)固定位置懸浮窗口的相關(guān)技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2015-04-04JavaScript中valueOf函數(shù)與toString方法深入理解
基本上,所有JS數(shù)據(jù)類型都擁有valueOf和toString這兩個(gè)方法,null除外。它們倆解決javascript值運(yùn)算與顯示的問題,本文將詳細(xì)介紹,有需要的朋友可以參考下2012-12-12基于HTML+JS實(shí)現(xiàn)簡單的年齡計(jì)算器
JavaScript提供了一些內(nèi)置的日期和時(shí)間函數(shù),有助于從日期(出生日期)開始計(jì)算年齡。本文主要介紹了使用這些JavaScript方法,制作一個(gè)簡單的年齡計(jì)算器,快來跟隨小編一起學(xué)習(xí)學(xué)習(xí)吧2021-12-12js 調(diào)用父窗口的具體實(shí)現(xiàn)代碼
想要實(shí)現(xiàn)如題所示:父窗體需要頂一個(gè)show()方法,具體實(shí)現(xiàn)代碼如下,感興趣的朋友可以參考下哈,希望對(duì)大家有所幫助2013-07-07javascript克隆元素樣式的實(shí)現(xiàn)代碼
這是一個(gè)實(shí)驗(yàn)用的玩意,它可以克隆指定元素的最終樣式,并包裝成一個(gè)css類,它還可以證明Oprea 11.10 是個(gè)混球2011-10-10js 下拉菜單點(diǎn)擊旁邊收起實(shí)現(xiàn)(踩坑記)
這篇文章主要介紹了js 下拉菜單點(diǎn)擊旁邊收起實(shí)現(xiàn)(踩坑記),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09artdialog的圖片/標(biāo)題以及關(guān)閉按鈕不顯示的解決方法
正如標(biāo)題所言不顯示的原因是因其它c(diǎn)ss樣式文件中包含div{ overflow:hidden; }引起的artdialog的圖片以及關(guān)閉按鈕不顯示,具體的解決方法如下,感興趣的朋友可以參考下哈2013-06-06