因為最近有博友反饋我的博文是直接翻譯的參考鏈接內的內容,所以我在這里要說明一下,以免引起不必要的誤會。
首先,我很喜歡 segmentfault 的交流和學習的氛圍,所以我很愿意在這里跟各位 SFer 交流學習心得,相互學習,共同進步。
第二,我做技術方面的工作不久,所以學習經歷也不是很長,但是我發現寫博客,總結自己的學習心得是個很好的學習習慣,至少對于我個人而言,我于此收益頗豐,所以我決定堅持一天至少寫一篇博客,以督促自己天天學習,吸取知識。
第三,由于我個人能力有限,除了有幾篇知識性的總結博文外,其余的博文都是直接翻譯的國外教程,在中間間接性地插入自己的一些想法和筆記,其主要目的是為了方便自己回顧記憶。之所以把博文的名字命名為《細說 Javascript xxx 篇》這種格式,是鑒于 segmentfault 暫時還沒有個人標簽的功能,這樣比較適合我個人進行歸納分類。
第四,我每篇博文后面都附有參考鏈接,由于我個人能力有限,所以有些地方可能自己理解或翻譯的不恰當,那么博友們可以點擊參考鏈接直接看原文的內容。
最后,我想說的是,我之所以在 segmentfault 寫博客,主要目的就是為了能與大家多多交流,彼此相互學習,我相信大家來 segmentfault 的目的大體都是這樣的,所以我希望在 segmentfault 這個優秀的平臺獲得知識取得進步的同時,也能為 segmentfault 貢獻自己的一份力量。
言歸真正,接下來我們討論 Javascript 的 arguments 對象。
每一個 Javascript 函數都能在自己作用域內訪問一個特殊的變量 - arguments。這個變量含有一個傳遞給函數的所有參數的列表。
arguments 對象不是一個數組。盡管在語法上它跟數組有相同的地方,例如它擁有 length 屬性。但它并不是從 Array.prototype 繼承而來,實際上,它就是一個對象。
因此,我們不能直接對 arguments 使用一些數組的方法,例如 push, pop 或 slice 等。 所以為了使用這些方法,我們就需要將其轉換為一個真正的數組。
下面的代碼將會返回一個包含 arguments 對象所有元素的數組。
Array.prototype.slice.call(arguments);
由于轉化的速度很慢,所以在性能要求嚴格的程序中不建議這樣做。
傳遞參數下面是一種比較推薦的方法,將 arguments 對象從一個函數傳遞到另一個函數。
function foo() { bar.apply(null, arguments); } function bar(a, b, c) { // do stuff here }
另外還有一個比較巧妙的方法,就是同時使用 call 和 apply 快速創建一個解綁的外層方法。
function Foo() {} Foo.prototype.method = function(a, b, c) { console.log(this, a, b, c); }; // Create an unbound version of "method" // It takes the parameters: this, arg1, arg2...argN Foo.method = function() { // Result: Foo.prototype.method.call(this, arg1, arg2... argN) Function.call.apply(Foo.prototype.method, arguments); };函數形參和 arguments 屬性的關系
arguments 對象為它自身屬性和函數的形參都創建了 getter 和 setter 方法。
因此,修改函數的形參會影響對應的 arguments 對象的屬性值,反之亦然。
function foo(a, b, c) { arguments[0] = 2; a; // 2 b = 4; arguments[1]; // 4 var d = c; d = 9; c; // 3 } foo(1, 2, 3);性能問題
arguments 只在兩種情況下不會被創建,一是在函數內部被聲明為局部變量,二是當做函數的形參。其他情況,arguments 對象總是會被創建。
由于 getter 和 setter 方法總是會隨著 arguments 對象的創建而創建,因此使用 arguments 對性能本身幾乎沒有影響。
然而,有一種情形會嚴重影響 Javascript 的性能,那就是使用 arguments.callee。
function foo() { arguments.callee; // do something with this function object arguments.callee.caller; // and the calling function object } function bigLoop() { for(var i = 0; i < 100000; i++) { foo(); // Would normally be inlined... } }
在上述代碼中,foo 函數不再是一個簡單的內聯擴展,因為它需要知道它自身以及它的調用者(caller)。這不僅抵消了內聯擴展所帶來的性能提升,同時也破壞了函數的封裝性,因為函數本身可能需要依賴于一個特定的調用背景。
因此,建議大家盡量不要使用 arguments.callee。
http://bonsaiden.github.io/JavaScript-Garden/#function.arguments
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/87514.html
摘要:操作符還有可能是設計中最大缺陷,因為它幾乎是完全破損的。由于用法與調用函數的語法相似,因此常被誤以為是函數調用,實際上并不存在名為的函數,只是一個操作符而已。而列則表示對象內部的屬性。屬性文檔中明確地給出了獲得屬性的途徑,就是使用。 typeof 操作符(還有 instanceof)可能是 Javascript 設計中最大缺陷,因為它幾乎是完全破損的。由于 typeof 用法與調用函數...
摘要:因為是弱類型語言,所以它會在任何可能的情形下對變量進行強制類型轉換。內置類型的構造函數調用內置類型的構造函數時,是否使用關鍵字將表現得大不相同。傳遞字面值或非對象值也會造成強制類型轉換的現象。最好的方法就是顯示地將值轉換為,或三種類型之一。 因為 Javascript 是弱類型語言,所以它會在任何可能的情形下對變量進行強制類型轉換。 // These are true new Num...
摘要:什么是函數引用的原話函數是一組可以隨時隨地運行的語句。函數是由這樣的方式進行聲明的關鍵字函數名一組參數,以及置于括號中的待執行代碼。 什么是函數? 引用 W3School 的原話: 函數是一組可以隨時隨地運行的語句。 函數是 ECMAScript 的核心。 函數是由這樣的方式進行聲明的:關鍵字 function、函數名、一組參數,以及置于括號中的待執行代碼。 函數的基本語法是這樣的:...
摘要:第二是,由于會遍歷整個原型鏈,所以當原型鏈過長時,會對性能造成影響。總結建議養成過濾屬性的好習慣,不要對運行環境做任何假設,也無論原生的原型對象是否被擴展。 如同 in 運算符一樣,使用 for in 循環遍歷對象屬性時,也將往上遍歷整個原型鏈。 // Poisoning Object.prototype Object.prototype.bar = 1; var foo = {m...
摘要:并沒有類繼承模型,而是使用原型對象進行原型式繼承。我們舉例說明原型鏈查找機制當訪問一個對象的屬性時,會從對象本身開始往上遍歷整個原型鏈,直到找到對應屬性為止。原始類型有以下五種型。此外,試圖查找一個不存在屬性時將會遍歷整個原型鏈。 Javascript 并沒有類繼承模型,而是使用原型對象 prototype 進行原型式繼承。 盡管人們經常將此看做是 Javascript 的一個缺點,然...
閱讀 2641·2021-10-12 10:12
閱讀 787·2019-08-29 17:25
閱讀 2790·2019-08-29 17:24
閱讀 3219·2019-08-29 17:19
閱讀 1804·2019-08-29 15:39
閱讀 3048·2019-08-26 16:50
閱讀 1992·2019-08-26 12:17
閱讀 2700·2019-08-26 12:16