摘要:對象被傳遞到從句中被捕獲。一些語言提供了尾遞歸優化。這意味著如果一個函數返回自身遞歸調用的結果,那么調用的過程會被替換為一個循環,可以顯著提高速度。構建一個帶尾遞歸的函數。語言精粹讀書筆記函數
第四章 函數 Functions (二) 參數 arguments
arguments數組: 函數可以通過此參數訪問所有它被調用時傳遞給它的參數列表,包括哪些沒有被分配給函數聲明時定義的形式參數的多余參數。
類似數組"(array-like)"的對象。arguments擁有一個length屬性,沒有任何數組方法。
返回 returnreturn被執行,函數立刻返回而不再執行余下的語句
一個函數總是會返回一個值,沒有指定返回值,則返回 undefined
使用 new 調用函數,且返回值不是一個對象,則返回this (該新對象)
異常 Exceptions異常是干擾程序的正常流程的不尋常(但并非完全是出乎意料的)事故
try { if(false) { throw { name:"TypeError", message:"number is required" } } }catch(e) { document.write(e.name + ": "+e.message) }
throw 語句中斷函數的運行。對象被傳遞到catch 從句中被捕獲。
擴充類型的功能通過給Function.prototype 增加方法,來使得該方法對所有函數可用:
Function.prototype.method = function(name,func) { this.prototype[name] = func; return this; }
這樣在函數,數組,字符串,數字,正則表達式和布爾值等基本類型的構造函數上添加方法時,就可以省去prototype 這幾個字符。使得對應的所有變量都適用改方法
為Number類型加上一個取整方法
Number.method("integer",function(){ return Math[this<0?"ceil":"floor"](this); });
為String加上一個去除首尾空白的方法
String.method("trim",function(){ return this.replace(/^s+|s+$/g,""); })
與類庫一起混用是,在確定沒有該方法時才添加它
// 符合條件時才增加方法 Function.prototype.method = function(name,func) { if(!this.prototype[name]) { this.prototype[name] = func; } return this; }遞歸
直接或者間接地調用自身的一種函數,它把一個問題分解為一組相似的子問題
經典的遞歸問題漢諾塔。塔上有3根柱子(1,2,3)和一套子直徑各不相同的空心圓盤。
開始盤子從小到大的順序堆疊在1號柱子上,目標是要經過2號柱子全部移動到3號柱子上,中間不允許較大的盤放在較小的盤上;
分解成子問題:
將1號柱子上的從上到下的n-1個盤利用3號柱子移動到2號柱子上。
將1號柱子上最下面的一個盤,直接移動到3號柱子上.
最后把2號柱子上n-1個盤利用遞歸調用方法,全部移動到3號柱子上。
var hanoi = function(disc,src,aux,dst) { if(disc > 0) { hanoi(disc -1,src,dst,aux); document.writeln("Move disc "+disc + " from "+src+"to "+dst); hanoi(disc-1,aux,src,dst) } }; hanoi(3,"Src","Aux","Dst"); // Move disc 1 from Srcto Dst Move disc 2 from Srcto Aux Move disc 1 from Dstto Aux Move disc 3 from Srcto Dst Move disc 1 from Auxto Src Move disc 2 from Auxto Dst Move disc 1 from Srcto Dst
利用遞歸高效地操作樹形結構,比如瀏覽器端的文檔對象模型(DOM),
var walk_the_DOM = function walk(node,func) { func(node); node = node.firstChild; while(node) { walk(node,func); node = node.nextSibling; } } // 定義 getElementsByAttribute 函數, //它以一個屬性名稱字符串和一個可選的匹配值作為參數。 var getElementsByAttribute = function(att,value) { var results = []; walk_the_DOM(document.body,function(node) { var actual = node.nodeType === 1 $$ node.getAttribute(att); if(typeof actual === "string" && (actual === value || typeof value != "string")) { results.push(node) } }); return results; }
一些語言提供了尾遞歸優化。這意味著如果一個函數返回自身遞歸調用的結果,那么調用的過程會被替換為一個循環,可以顯著提高速度。
//構建一個帶尾遞歸的函數。因為它會返回自身調用的結果 // 實現 factorial = n*(n-1)(n-2)... 1; var factorial = function factorial(i,a) { a = a || 1; if(i<2) { return a; } return factorial(i-1,a*i); }; document.writeln(factorial(4)) // 4*3*2*1 = 24作用域
作用域控制著變量與參數的可見性及生命周期
函數作用域: 定義在函數中的參數和變量在函數外部是不可見的,而在一個函數內部任何位置定義的變量,在該函數內部任何地方都可見。
在JavaScript中缺少會計作用域,最好的做法是在函數體的頂部聲明函數中可能用到的所有變量。
閉包 Closure閉包:函數可以訪問它被創建時所處的上下文環境。內部函數可以訪問外部函數的實際變量而無需復制
作用域的好處是內部函數可以訪問定義它們的外部函數的參數和變量(除了this 和arguments)
內部函數擁有比它的外部函數更長的生命周期。
var myObject = (function(){ var value = 0; return { increment:function(inc) { value += typeof inc === "number" ?inc :1; }, getValue:function() { return value; } } })()
上面定義的value變量對increment和getValue方法總是可用的,但函數的作用域使得它對其他的程序來說是不可見的
回調 Callbacks異步請求,提供一個服務器的響應到達是隨即觸發的回調函數,模塊 Module
異步函數立即返回。
使用 函數 和 閉包創造模塊
模板的一般形式:
一個定義了私有變量和函數的函數
利用閉包創建可以訪問私有變量和函數的特權函數
返回這個特權函數,或者把它們保存到一個可訪問到的地方。
利用前面使用的method方法,為String 增加一個deentityify 方法,尋找字符串中的HTML字符實體并把它們替換為對應的字符。
String.method("deentityify",function(){ // 字符實體表,它映射字符實體的名字到對應的字符 var entity = { quot: """, lt:"<", gt:">" }; // 返回 deetityify 方法 return function() { // 下面就是deetityify方法, return this.replace(/&([^&;]+);/g, function(a,b){ var r = entity[b]; return typeof r === "string"?r:a; } ) } }());
最后,使用()運算符立刻調用我們剛剛構造出來的函數,這個調用所創建并返回的函數才是deentityify方法
document.writeln("<">".deentityify()) // <">級聯
讓執行后的函數返回this 而不是 undefined,就可以啟用級聯
一個級聯中就,我們可以在多帶帶一條語句中依次調用同一個對象的很多方法。一個啟用了Ajax類庫可能允許我們以這樣的形式去編碼
getElement("myBoxDiv") .move(300,150) .width(100) .height(200) ... .tip("This box is resizeable")
上面的例子中,每次調用返回的結果都會被下一次調用所用。
柯里化柯里化允許我們把函數與傳遞給它的參數相結合,產生一個新的函數
Function.method("curry",function(){ var slice = Array.prototype.slice, args = slice.apply(arguments), that = this; return function() { return that.apply(null,args.concat(slice.apply(arguments))) } }) function add (a,b) {return a+b} add.curry(1)(6) //7記憶
函數可以將先前操作的結果記錄在某個對象里,從而避免無謂的重復運算,這種優化被稱為記憶
以Fibonacci數列為例,一個Fibonacci數字是之前兩個Fibonacci數字之和。最前面的兩個數字時0和1
var fibonacci = function (n) { return n<2? n:fibonacci(n-1) + fibonacci(n-2) } for(var i =0 ;i< = 10;i+=1) { document.writeln("http://"+i+": "+fibonacci(i)) } //0: 0 //1: 1 //2: 1 //3: 2 //4: 3 //5: 5 //6: 8 //7: 13 //8: 21 //9: 34 //10: 55
改進,利用memo數組保存我們的存儲結果,存儲結果可以隱藏在閉包中。
var fibonacci = function() { var memo = [0,1]; var fib = function(n) { var result = memo[n]; // 檢查結果是否已存在,如果已經存在,就立刻返回這個結果 if(typeof result !== "number") { result = fib(n-1) + fib(n-2); memo[n]= result; } return result }; return fib; }(); fibonacci(10) //55
推而廣之,編寫一個函數來幫助我們構造帶記憶功能的函數。
var memoizer = function(memo,formula) { var recur = function(n) { var result = memo[n]; if(typeof result !== "number") { result = formula(recur,n); memo[n] = result; } return result; }; return recur; } var fibonacci = memoizer([0,1],function(recur,n) { return recur(n-1) + recur(n-2); }); fibonacci(10) // 55
《JavaScript 語言精粹》讀書筆記 - 函數
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/93238.html
摘要:語言精粹讀書筆記第四章函數函數字面量函數字面量包含個部分第一部分,保留字第二部分,函數名,它可以被忽略。這個超級延遲綁定使得函數對高度復用。構造器調用模式一個函數,如果創建的目的就是希望結合的前綴來調用,那它就被稱為構造器構造。 《JavaScript 語言精粹》 讀書筆記 第四章 函數 Functions 函數字面量 函數字面量包含4個部分: 第一部分, 保留字 function...
摘要:使用構造器有個嚴重的危害,如果在調用構造器函數的時候忘記使用前綴,不僅不會綁定到新對象,還會污染全局變量原型模式原型模式中,我們采用對象來繼承。 構造器調用模式 當一個函數對象被創建時,Function構造器會運行類似這樣的代碼: this.prototype = {constructor: this} new一個函數事會發生: Function.method(new, functio...
摘要:于是我就先把這本薄的經典書語言精粹修訂版豆瓣讀書本書簡介總共章,除去附錄,才頁,讀完并記錄了一些筆記。讀書筆記還可以分享給別人看。編程語言第版定義了的標準。程序檢查時丟棄值為函數的屬性。 之前看到這篇文章,前端網老姚淺談:怎么學JavaScript?,說到怎么學習JavaScript,那就是看書、分析源碼。10本書讀2遍的好處,應該大于一本書讀20遍。看書主動學習,看視頻是被動學習。看...
摘要:第條盡量少使用全局對象避免聲明全局變量盡量聲明局部變量避免對全局變量增加屬性第條始終聲明局部變量第條避免使用語句第條熟練使用閉包的函數值包含了比調用他們時執行所需要的代碼還要更多的信息。那些在其所涵蓋的作用域內跟蹤變量的函數稱為閉包。 書還沒看完。一遍看,一遍寫讀書筆記。 這本書的序是JavaScript之父Brendan Eich寫的,作者是JavaScript標準化委員會專家。可想...
摘要:前言由于最近的項目用到了一些的代碼,所以我帶著好奇心,認真閱讀了這本書,粗略地了解語言的基本結構和特性,對于一些不熟悉的新概念,以記錄的形式加強印象,也是對學習的反思總結。 前言 由于最近的項目用到了一些js的代碼,所以我帶著好奇心,認真閱讀了這本書,粗略地了解js語言的基本結構和特性,對于一些不熟悉的新概念,以記錄的形式加強印象,也是對學習的反思總結。 一、字面量(literals...
閱讀 3073·2021-11-24 11:14
閱讀 3504·2021-11-22 15:22
閱讀 3204·2021-09-27 13:36
閱讀 717·2021-08-31 14:29
閱讀 1331·2019-08-30 15:55
閱讀 1761·2019-08-29 17:29
閱讀 1148·2019-08-29 16:24
閱讀 2410·2019-08-26 13:48