<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                **概述** [[mozilla.org]](https://developer.mozilla.org/en-US/docs/Web/JavaScript) JavaScript是一種基于原型編程、多范式的動態腳本語言,并且支持面向對象、命令式和聲明式(如函數式編程)風格。 JavaScript 的標準是 ECMAScript 。截至 2012 年,所有的現代瀏覽器都完整支持 ECMAScript 5.1,舊式的瀏覽器至少支持 ECMAScript 3 標準。2015年6月17日,ECMA國際組織(Ecma International,一個歐洲標準化組織)發布了 ECMAScript 的第六版,該版本正式名稱為ECMAScript 2015,但通常被稱為 ECMAScript 6 或者ES6。自此,ECMAScript每年發布一次新標準。 與大多數編程語言不同,JavaScript 沒有輸入或輸出的概念。它是一個在宿主環境(host environment)下運行的腳本語言,任何與外界溝通的機制都是由宿主環境提供的。瀏覽器是最常見的宿主環境,但在非常多的其他程序中也包含 JavaScript 解釋器,如 Adobe Acrobat、Photoshop、SVG 圖像、Yahoo! 的 Widget 引擎,以及 Node.js 之類的服務器端環境。JavaScript 的實際應用遠不止這些,除此之外還有 NoSQL 數據庫(如開源的 Apache CouchDB)、嵌入式計算機,以及包括 GNOME (注:GNU/Linux 上最流行的 GUI 之一)在內的桌面環境等等。 HTML是用來存儲網頁內容的,CSS是用來定義這些內容的顯示樣式的,而JavaScript是用來創造豐富的頁面效果或者網頁應用的。 但是,如果從瀏覽器的范疇去理解“JavaScript”這個術語,它包含了截然不同的兩個方面。一個是JavaScript的核心語言(ECMAScript),另一個是DOM(文檔對象模型)。 ---- 目錄: [TOC] ---- ## X JavaScript 標準庫 [參考內容:JavaScript 標準庫](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects) JavaScript 標準庫中的標準內置對象(Standard built-in objects)或稱**全局的對象**( global objects ),不要和 "**全局對象**(global object)" 混淆。這里說的全局的對象是說在**全局作用域里的內的對象**。 "全局對象 (global object)” 是一個Global類的對象。可以在全局作用域里,用`this`訪問(但只有在非嚴格模式下才可以,在嚴格模式下得到的是`undefined`)。實際上,全局作用域就是包含了全局對象的屬性,還有它繼承來的屬性。 全局作用域中的其他對象可以由用戶的腳本創建或由宿主程序提供。瀏覽器作為最常見的宿主程序,其所提供的宿主對象的說明可以在這里找到:[API 參考](https://developer.mozilla.org/zh-CN/docs/Web/API)。 ### global對象(全局對象) 《JS高級程序設計》中談到,global對象可以說是ECMAScript中對特別的一個對象了,因為不管你從什么角度上看,這個對象都是不存在的。從某種意義上講,它是一個終極的“兜底兒對象”,換句話說呢,就是不屬于任何其他對象的屬性和方法,最終都是它的屬性和方法。我理解為,這個global對象呢,就是整個JS的“老祖宗”,找不到歸屬的那些“子子孫孫”都可以到它這里來認祖歸宗。所有在全局作用域中定義的屬性和函數,都是global對象的屬性和方法,比如isNaN()、parseInt()以及parseFloat()等,實際都是它的方法;還有就是常見的一些特殊值,如:NaN、undefined等都是它的屬性,以及一些構造函數Object、Array等也都是它的方法。總之,記住一點:global對象就是“老祖宗”,所有找不到歸屬的就都是它的。 ### window對象 前面說了global對象是“老祖宗”,那有人該問了,你把window對象置于何地呢?對,javascript這門語言現在這么紅火很大部分原因是因為W3C將它作為寫頁面的官方腳本語言,但別忘了js它不僅僅可以用來寫頁面,也就是不僅僅可以用在瀏覽器中。window對象是相對于web瀏覽器而言的,它并不是ECMAScripta規定的內置對象,內置對象的定義是:“由ECMAScript實現提供的、不依賴于宿主環境的對象,這些對象在ECMAScript程序執行之前就已經存在了。”window對象是宿主對象也就是在一定的環境中才會生成的對象(這里也就是指瀏覽器),而global對象是在任何環境中都存在的。window對象具體也就是指瀏覽器打開的那個窗口。 ### document對象 簡單來說,document對象是window對象的一個屬性,是顯示于窗口內的一個文檔。而window對象則是一個頂層對象,它不是另一個對象的屬性。document可以理解為文檔,就是你的網頁,而window是你的窗口,就是你的瀏覽器包含的。它們倆在沒有框架的情況下可以說是等同的,在有框架的情況下就要區別對待了。 ## 1. JavaScript 技術概覽 [概述](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/JavaScript_technologies_overview) HTML是用來存儲網頁內容的,CSS是用來定義這些內容的顯示樣式的,而JavaScript是用來創造豐富的頁面效果或者網頁應用的。 但是,如果從瀏覽器的范疇去理解“JavaScript”這個術語,它包含了截然不同的兩個方面。一個是JavaScript的核心語言(ECMAScript),另一個是DOM(文檔對象模型)。 ### X.1 JavaScript核心語言 (ECMAScript) JavaScript的核心語言是ECMAScript。ECMAScript是由ECMA TC39委員會進行標準化的一門編程語言,其最新版本是``ECMAScript 7.0``。 核心語言同樣可以被用在非瀏覽器環境中,例如 ``node.js``。 **ECMAScript**([有關資源]()) 定義了: - 語法(解析規則,關鍵字,流程控制,對象初始化等) - 錯誤處理機制(throw, try/catch 以及用戶自定義錯誤類型的能力) - 類型(布爾值,數字,字符串,函數,對象等) - 全局對象。在瀏覽器環境中,這個全局對象就是 window 對象,但是 ECMAScript 只定義與瀏覽器無關的 APIs(例如,parseInt, parseFloat, decodeURI, encodeURI 等) - 基于原型的繼承機制 - 內置對象和函數(JSON,Math,Array.prototype 方法,Object introspection 方法等) - 嚴格模式 **瀏覽器支持** 截止2014年8月份,主流瀏覽器的最新版本都已經支持ECMAScript 5.1,但是舊版本的瀏覽器大都僅支持ECMAScript 3和ECMAScript 5的部分標準。[這里](http://kangax.github.io/compat-table/es5/)是一些關于ECMAScript 5的瀏覽器支持情況的資料。如今,主流瀏覽器的最新版本已經支持 ECMAScript 6 的大部分標準。 ECMA 委員會已經在 2015年6月17號,正式發布了第6版標準。 ### X.2 DOM API **WebIDL** [WebIDL (an interface definition language, )](https://heycam.github.io/webidl/)定義了ECMAScript和DOM技術之間的交互規范。 **DOM核心** 文檔對象模型(DOM, Document Object Model)是用來表達HTML,XHTML及XML文檔中的對象或與其進行交互的約定,它是跨平臺的,并且與編程語言無關。通過調用DOM樹上對象的方法可以操縱這些對象。文檔對象模型核心是由W3C進行標準化的,它將HTML和XML文檔抽象成對象,并在其上定義接口以及操縱這些對象的機制,這些定義都是與編程語言無關的。 - [DOM核心](https://dom.spec.whatwg.org/)中定義了文檔結構,樹模型,以及 DOM事件架構,包括:Node, Element, DocumentFragment, Document, DOMImplementation, Event, EventTarget等。 -[ DOM事件](https://w3c.github.io/uievents/)中包括DOM事件架構不太嚴格的定義以及一些特殊事件。 - [DOM元素遍歷](https://www.w3.org/TR/DOM-Level-2-Traversal-Range/traversal.html) 以及 [DOM Range](https://dom.spec.whatwg.org/#ranges) 對象等其它內容。 從ECMAScript的角度來看,DOM規范中定義的對象被稱作“宿主對象”。 **HTML DOM** [HTML](https://html.spec.whatwg.org/multipage/)是一種網頁標記語言,它在DOM核心抽象概念之上,還定義了元素的含義,比如元素的``className``屬性以及 ``document.body``對象等。 HTML規范同時還約束了元素之間的關系,例如無序列表ul元素中,只能以li元素作為子元素來表達列表項。還有就是禁止使用標準中未定義的元素和屬性。 想了解更多關于[Document對象](https://developer.mozilla.org/zh-CN/docs/Web/API/document)、[Window對象](https://developer.mozilla.org/zh-CN/docs/Web/API/Window)以及其他[DOM元素](https://developer.mozilla.org/zh-CN/docs/Web/API/Document_Object_Model)的信息?請訪問Gecko DOM文檔。 ### X.3 國際化API 由Ecma TC39進行標準化的ECMAScript國際化API規范是在ECMAScript語言規范之上額外增加的。國際化API為JavaScript提供了規則排序(字符串比較),數字格式化,日期時間格式化等功能,能夠讓應用根據實際需要選擇語言或功能。本標準在2012年12月份審批通過,可以在[Intl對象](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl)頁面查看瀏覽器的實現情況。 ### X.4 其他值得關注的API - HTML標準中`Window`接口首次對setTimeout和setInterval函數進行定義。 - `XMLHttpRequest`:用來發起異步HTTP請求的API。 - `CSS 對象模型` :用于將CSS規則抽象成對象。 - `WebWorkers`: 是用來并行計算的API。 - `WebSockets`:是用來實現雙向Socket通信的API。 - `Canvas 2D Context`:canvas元素的繪圖API。 ### X.5 瀏覽器支持 自2011年6月以來,W3C,特別是WHATWG都在對舊特性進行細節定義,以提高互用性。瀏覽器也基于這些更加詳細的規范提升它們的實現方式。 要實現跨瀏覽器的兼容性,一個常見的但可能不是最可靠的方式就是使用JavaScript庫。這些庫對于DOM特性進行抽象,以確保它們所提供的API在不同的瀏覽器上行為一致。被廣泛采用的框架有[jQuery](http://jquery.com/),[prototype](http://prototypejs.org/)和[YUI](https://yuilibrary.com/)。 ## x.1 值屬性 (Value properties) 這些全局屬性返回一個簡單值,這些值沒有自己的屬性和方法。 > > - Infinity > - NaN > - undefined > - null literal ## x.2 函數屬性 (Function properties) 全局函數可以直接調用,不需要在調用時指定所屬對象,執行結束后會將結果直接返回給調用者。 ### x.2.1 函數 [官方網頁](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Functions) ### x.2.2 預定義函數 [官方網頁](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Functions) > - eval() > - isFinite() > - isNaN() > - parseFloat() > - parseInt() > - decodeURI() > - decodeURIComponent() > - encodeURI() > - encodeURIComponent() > - uneval() (不再標準化) > - escape() (不再使用) > - unescape() (不再使用) ## x.3 基本對象 (Fundamental objects) 基本對象是定義或使用其他對象的基礎。基本對象包括一般對象、函數對象和錯誤對象。 > > - Object > - Function > - Boolean > - Symbol > - Error > - EvalError > - InternalError > - RangeError > - ReferenceError > - SyntaxError > - TypeError > - URIError ## x.4 數字和日期對象 (Numbers and dates) 用來表示數字、日期和執行數學計算的對象。 > > - Number > - Math > - Date #### x.4.1 Number對象 #### x.4.2 Math對象 #### x.4.3 Date對象 [Date對象](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Date)基于1970年1月1日(世界標準時間)起的毫秒數。 ~~~JavaScript var today = new Date(); var today = new Date(1453094034000); // by timestamp(accurate to the millimeter) var birthday = new Date('December 17, 1995 03:24:00'); var birthday = new Date('1995-12-17T03:24:00'); var birthday = new Date(1995, 11, 17); var birthday = new Date(1995, 11, 17, 3, 24, 0); var unixTimestamp = Date.now(); // in milliseconds ~~~ **構造函數** ~~~JavaScript new Date(); new Date(value); new Date(dateString); new Date(year, month[, day[, hour[, minutes[, seconds[, milliseconds]]]]]); ~~~ > * 只能通過調用 Date 構造函數來實例化日期對象。以常規函數調用它(即不加 new 操作符)將會返回一個字符串,而不是一個日期對象。另外,不像其他JavaScript 類型,Date 對象沒有`字面量格式`。 > * 當Date作為構造函數調用并傳入多個參數時,如果數值大于合理范圍時(如月份為13或者分鐘數為70),相鄰的數值會被調整。比如 new Date(2013, 13, 1)等于new Date(2014, 1, 1),它們都表示日期2014-02-01(注意月份是從0開始的)。其他數值也是類似,new Date(2013, 2, 1, 0, 70)等于new Date(2013, 2, 1, 1, 10),都表示時間2013-03-01T01:10:00。 > * 當Date作為構造函數調用并傳入多個參數時,所定義參數代表的是當地時間。如果需要世界協調時,使用 new Date({{jsxref("Date.UTC()", "Date.UTC(...)")}}) 和相同參數 `value`:代表自1970年1月1日00:00:00 (世界標準時間) 起經過的毫秒數。 `dateString`:表示日期的字符串值。該字符串應該能被 [Date.parse()](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Date/parse) 方法識別(符合 [IETF-compliant RFC 2822 timestamps](https://tools.ietf.org/html/rfc2822#page-14) 或 [version of ISO8601](http://www.ecma-international.org/ecma-262/5.1/#sec-15.9.1.15))。 `year`:代表年份的整數值。為了避免2000年問題最好指定4位數的年份; 使用 1998, 而不要用 98. `month`:代表月份的整數值從0(1月)到11(12月)。 `day`:代表一個月中的第幾天的整數值,從1開始。 `hour`:代表一天中的小時數的整數值 (24小時制)。 `minute`:分鐘數。 `second`:秒數。 `millisecond`: 表示時間的毫秒部分的整數值。 **描述** * 如果沒有輸入任何參數,則Date的構造器會依據系統設置的當前時間來創建一個Date對象。 * 如果提供了至少兩個參數,其余的參數均會默認設置為1(如果沒有提供day參數)或者0。 * JavaScript的時間是由世界標準時間(UTC)1970年1月1日開始,用毫秒計時,一天由86,400,000毫秒組成。Date對象的范圍是-100,000,000天至100,000,000天(等效的毫秒值)。 * JavaScript的Date對象為跨平臺提供了統一的行為。時間屬性可以在不同的系統中表示相同的時刻,而如果使用了本地時間對象,則反映當地的時間。 * JavaScript 的Date對象提供了數個UTC時間的方法,也相應提供了當地時間的方法。`UTC`,也就是我們所說的格林威治時間,指的是time中的世界時間標準。而`當地時間`則是指執行JavaScript的客戶端電腦所設置的時間。 * 以一個函數的形式來調用JavaScript的Date對象(i.e., 不使用 new 操作符)會返回一個代表當前日期和時間的字符串。 **屬性** `Date.prototype`:允許為 Date 實例對象添加屬性。 `Date.length`:Date.length 的值是 7。這是該構造函數可接受的參數個數。 **方法** `Date.now()`:返回自 1970-1-1 00:00:00 UTC (世界標準時間)至今所經過的毫秒數。 `Date.parse()`:解析一個表示日期的字符串,并返回從 1970-1-1 00:00:00 所經過的毫秒數。 `Date.UTC()`:接受和構造函數最長形式的參數相同的參數(從2到7),并返回從 1970-01-01 00:00:00 UTC 開始所經過的毫秒數。 **Date.prototype方法** * Getter,19個 * Setter,16 * Conversion getter,13個 ### x.5 字符處理 (Text processing) 用來表示和操作字符串的對象。 > > - String > - RegExp ### x.6 可索引的集合對象 (Indexed collections) 按照索引值來排序的數據集合,包括數組和類型數組,以及類數組結構的對象。 > > - Array > - Int8Array > - Uint8Array > - Uint8ClampedArray > - Int16Array > - Uint16Array > - Int32Array > - Uint32Array > - Float32Array > - Float64Array ### x.7 使用鍵的集合對象 (Keyed collections) 這些集合對象在存儲數據時會使用到鍵,支持按照插入順序來迭代元素。 > > - Map > - Set > - WeakMap > - WeakSet ### x.8 結構化數據 (Structured data) > > - ArrayBuffer > - DataView > - JSON > - SharedArrayBuffer (實驗開發中,不適用生產環境) > - Atomics (實驗開發中,不適用生產環境) ### x.9 控制抽象對象 (Control abstraction objects) > > - Promise > - Generator > - GeneratorFunction > - AsyncFunction (實驗開發中,不適用生產環境) ### x.11 反射 (Reflection) > > - Reflect > - Proxy ### x.12 國際化 (Internationalization) 為了支持多語言處理而加入ECMAScript的對象。 > > - Intl > - Intl.Collator > - Intl.DateTimeFormat > - Intl.NumberFormat ### x.13 WebAssembly > > - WebAssembly > - WebAssembly.Module > - WebAssembly.Instance > - WebAssembly.Memory > - WebAssembly.Table > - WebAssembly.CompileError > - WebAssembly.LinkError > - WebAssembly.RuntimeError ### x.14 其他 > > - arguments ### x.15 矢量集合 (Vector collections )(實驗開發中,不適用生產環境) SIMD 矢量集合中的數據會被組織為一個數據序列。 ## x. 調試(console對象) [瀏覽器控制臺(console對象)](http://blog.csdn.net/gz_jmark/article/details/22997349) console對象代表瀏覽器的JavaScript控制臺。雖然它還不是標準,但是各大瀏覽器都原生支持,已經成為事實上的標準。 console對象主要有兩個作用: - 顯示網頁代碼運行時的錯誤信息。 - 提供了一個命令行接口,用來與網頁代碼互動。 ### x.1 console.log log方法用于在console窗口顯示信息。 如果參數是普通字符串,log方法將字符串內容顯示在console窗口。 ~~~js console.log("Hello World") // Hello World console.log("a","b","c") // a b c ~~~ 如果參數是格式字符串(使用了格式占位符),log方法將占位符替換以后的內容,顯示在console窗口。 * %d, %i 整數 * %s 字符串 * %f 浮點數 * %o 對象的鏈接 * %c CSS格式字符串 ~~~js console.log("%c%s", "color: red; background: yellow; font-size: 24px;", "警告!"); ~~~ ### x.2 console.dir 輸出對象的信息,用于顯示一個對象的所有屬性。 ### x.3 console.table 對于某些復合類型的數據,console.table方法可以將其轉為表格顯示。 ### x.4 console.clear 對console窗口進行清屏,光標回到第一行。 ### x.5 console.trace 當前執行的代碼在堆棧中的調用路徑。 ## xx. 基于原型(prototype)的編程范式 2018-02-01 陳皓(左耳朵耗子,極客時間)[編程范式游記(7)- 基于原型的編程范式 ](https://time.geekbang.org/column/article/2741) 基于原型(prototype)的編程其實也是面向對象編程的一種方式。沒有 class 化的,直接使用對象。又叫,基于實例的編程。其主流的語言就是 JavaScript。 * 在基于類的語言中,一個新的實例通過類構造器和構造器可選的參數來構造,結果實例由類選定的行為和布局創建模型。 * 在基于原型的系統中構造對象有兩種方法,通過復制已有的對象或者通過擴展空對象創建。很多基于原型的系統提倡運行時原型的修改,而基于類的面向對象系統只有動態語言允許類在運行時被修改(Common Lisp、Dylan、Objective-C、Perl、Python、Ruby 和 Smalltalk)。 每個對象都有一個` __proto__ `的屬性,這個就是“原型”。 需要解釋一下 JavaScript 的兩個東西,一個是` __proto__`,另一個是 `prototype`. * `__proto__ `主要是安放在一個實際的對象中,用它來產生一個鏈接,一個原型鏈連,用于尋找方法名或屬性,等等。 * `prototype` 是用 new 來創建一個對象時構造` __proto__ `用的。它是構造函數的一個屬性。 在 JavaScript 中,對象有兩種表現形式, 一種是 Object [(ES5 關于 Object 的文檔)](http://www.ecma-international.org/ecma-262/5.1/#sec-15.2),一種是 Function [(ES5 關于 Object 的文檔)](http://www.ecma-international.org/ecma-262/5.1/#sec-15.2)。 我們可以簡單地認為,`__proto__ `是所有對象用于鏈接原型的一個指針,而 `prototype` 則是 Function 對象的屬性,其主要是用來當需要 new 一個對象時讓` __proto__ `指針所指向的地方。 對于超級對象 Function 而言, `Function.__proto__ `就是` Function.prototype`。 ~~~javascript // 一種構造函數寫法 function Foo(y) { this.y = y; } // 修改 Foo 的 prototype,加入一個成員變量 x Foo.prototype.x = 10; // 修改 Foo 的 prototype,加入一個成員函數 calculate Foo.prototype.calculate = function (z) { return this.x + this.y + z; }; // 現在,我們用 Foo 這個原型來創建 b 和 c var b = new Foo(20); var c = new Foo(30); // 調用原型中的方法,可以得到正確的值 b.calculate(30); // 60 c.calculate(40); // 80 ~~~ 那么,在內存中的布局是怎么樣的呢?大概是下面這個樣子。 ![javascript中的prototype](https://box.kancloud.cn/e4a5053894b27759103976720d29ab80_627x392.png) 我們可以測試一下: ~~~javascript b.__proto__ === Foo.prototype, // true c.__proto__ === Foo.prototype, // true b.constructor === Foo, // true c.constructor === Foo, // true Foo.prototype.constructor === Foo, // true b.calculate === b.__proto__.calculate, // true b.__proto__.calculate === Foo.prototype.calculate // true ~~~ 這里需要說明的是—`Foo.prototype` 自動創建了一個屬性 constructor,這是一個指向函數自己的一個 reference。這樣一來,對于實例 b 或 c 來說,就能訪問到這個繼承的 constructor 了。 >[info]注: 上面示例和圖示來源于[(JavaScript, The Core)](http://dmitrysoshnikov.com/ecmascript/javascript-the-core/) 一文。 “原型編程”中面向對象的編程玩法。 ~~~javascript //Person原型/對象 function Person(){} //Student原型/對象 var Student = function(){}; // 1. Student繼承Person Student.prototype=Object.create(Person.prototype); //2. 修改構造函數Student.prototype.constructor Student.prototype.constructor=Student; //3. student對象實例 var student = new Student(); ~~~ ![](https://box.kancloud.cn/d47a4aca192ab7cad7cdc669e14afe7f_986x617.JPG) >[info]注:在 ECMAScript 標準的第四版開始尋求使 JavaScript 提供基于類的構造,且 ECMAScript 第六版有提供 "class"(類) 作為原有的原型架構之上的語法糖,提供構建對象與處理繼承時的另一種語法。 這種在對象里面直接修改的玩法,雖然這個特性可以帶來運行時的靈活性,我們可以在運行時修改一個 prototype,給它增加甚至刪除屬性和方法。但是其帶來了執行的不確定性,也有安全性的問題,而代碼還變得不可預測,這有點黑科技的味道了。因為這些不像靜態類型系統,沒有一個不可變的契約對代碼的確定性有保證,所以,需要使用者來自己保證。 ## xx. 函數式編程(Functional Programming)的編程范式 [https://coolshell.cn/articles/17524.html](https://coolshell.cn/articles/17524.html) 我們把以前的過程式的編程范式叫做 Imperative Programming – 指令式編程,而把函數式的這種范式叫做 Declarative Programming – 聲明式編程。 階乘計算舉例: ~~~javascript const fact = (n)=>n==0 ? 1 : n * fact(n-1); fact(5);//120 ~~~ > ### Javascript的箭頭函數 [【參考文檔】](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions) ECMAScript2015 引入的箭頭表達式。箭頭函數其實都是匿名函數,其基本語法如下: ~~~Javascript (param1, param2, …, paramN) => { statements } (param1, param2, …, paramN) => expression // 等于 : => { return expression; } // 只有一個參數時,括號才可以不加: (singleParam) => { statements } singleParam => { statements } //如果沒有參數,就一定要加括號: () => { statements } ~~~ 下面是一些示例: ~~~Javascript var simple = a => a > 15 ? 15 : a; simple(16); // 15 simple(10); // 10 let max = (a, b) => a > b ? a : b; // Easy array filtering, mapping, ... var arr = [5, 6, 13, 0, 1, 18, 23]; var sum = arr.reduce((a, b) => a + b); // 66 var even = arr.filter(v => v % 2 == 0); // [6, 0, 18] var double = arr.map(v => v * 2); // [10, 12, 26, 0, 2, 36, 46] ~~~ 上面前兩個 simple 和 max 的例子都把箭頭函數賦值給了一個變量,于是它就有了一個名字。有時候,某些函數在聲明的時候就是調用的時候,尤其是函數式編程中,一個函數還對外返回函數的時候。比如下面的例子: ~~~javascript function MakePowerFn(power) { return function(base) { return Math.pow(base, power); } } power3 = MakePowerFn(3); //制造一個X的3次方的函數 power2 = MakePowerFn(2); //制造一個X的2次方的函數 console.log(power3(10)); //10的3次方 = 1000 console.log(power2(10)); //10的2次方 = 100 ~~~ 用箭頭函數,可以寫成: ~~~javascript MakePowerFn= power =>{ return base =>{ return Math.pow(base, power); } } ~~~ 如果用表達式的話,就不需要 { 和 }, 以及 return 語句,簡化: ~~~javascript MakePowerFn= (power)=>( (base) =>(Math.pow(base, power)) ) ~~~ 去掉括號和換行,更進一步簡化 ~~~javascript MakePowerFn= power=>base=>Math.pow(base, power) ~~~ >[danger] 自調用匿名函數是否可以用箭頭函數改寫?? ~~~javascript ;(function($,window,document,undefined){ //我們的代碼。。 //blah blah blah... })(jQuery,window,document); ~~~ > ### 匿名函數的遞歸 函數式編程立志于用函數表達式消除有狀態的函數,以及for/while循環,所以,在函數式編程的世界里是不應該用for/while循環的,而要改用遞歸(遞歸的性能很差,所以,一般是用尾遞歸來做優化,也就是把函數的計算的狀態當成參數一層一層的往下傳遞,這樣語言的編譯器或解釋器就不需要用函數棧來幫你保存函數的內部變量的狀態了)。 一般來說,遞歸的代碼就是函數自己調用自己,比如我們求階乘的代碼: ~~~javascript function fact(n){ return n==0 ? 1 : n * fact(n-1); } result = fact(5); ~~~ 對于匿名函數來說,我們可以把匿名函數當成一個參數傳給另外一個函數,因為函數的參數有名字,所以就可以調用自己了。 把上述fact中自己調用自己的名字去掉,如下所示: ~~~javascript function fact(func, n) { return n==0 ? 1 : n * func(func, n-1); } fact(fact, 5); //輸出120 ~~~ 然后,我們再把上面這個版本變成箭頭函數的匿名函數版(還要用一個fact來保存這個匿名函數): ~~~javascript var fact = (func, n) => ( n==0 ? 1 : n * func(func, n-1) ) fact(fact, 5) ~~~ 接下來,我們要讓匿名函數聲明的時候,就自己調用自己。 ~~~javascript ( (func, x) => func(func, x) ) ( //函數體 (func, n) => ( n==0 ? 1 : n * func(func, n-1) ), //第一個調用參數 5 //第二調用參數 ); ~~~ 也就是說,我們要把`(func, n) => ( n==0 ? 1 : n * func(func, n-1) )` 這個函數當成調用參數,傳給下面這個函數 `(func, x) => func(func, x)` > ### 動用高階函數的遞歸 上面這個遞歸的匿名函數在自己調用自己,所以,代碼中有hard code的實參。我們想實參去掉,如何去掉呢?需要一個函數做參數,然后返回這個函數的遞歸版本 ~~~javascript HighOrderFact = function(func){ return function(n){ return n==0 ? 1 : n * func(func)(n-1); }; }; ~~~ 調用函數時就為: ~~~javascript fact = HighOrderFact(HighOrderFact); fact(5); ~~~ 連起來寫就是: ~~~javascript HighOrderFact ( HighOrderFact ) ( 5 ) ~~~ 但是,這樣讓用戶來調用很不爽,所以,用一個函數把 HighOrderFact ( HighOrderFact ) 給代理一下: ~~~javascript fact = function ( hifunc ) { return hifunc ( hifunc ); } ( //調用參數是一個函數 function (func) { return function(n){ return n==0 ? 1 : n * func(func)(n-1); }; } ); fact(5); //于是我們就可以直接使用了 ~~~ 用箭頭函數重構一下, ~~~javascript fact = (highfunc => highfunc ( highfunc ) ) ( func => n => n==0 ? 1 : n * func(func)(n-1) ); ~~~ > ### 查找數組的函數式編程實現 正常的版本 ~~~javascript //正常的版本 function find (x, y) { for ( let i = 0; i < x.length; i++ ) { if ( x[i] == y ) return i; } return null; } let arr = [0,1,2,3,4,5] console.log(find(arr, 2)) console.log(find(arr, 8)) ~~~ 開始變身。 * 先把for干掉,搞成遞歸版本: ~~~javascript function find (x, y, i=0) { if ( i >= x.length ) return null; if ( x[i] == y ) return i; return find(x, y, i+1); } ~~~ * 然后,寫出帶實參的匿名函數的版本(注:其中的if代碼被重構成了 ?號表達式): ~~~javascript ( (func, x, y, i) => func(func, x, y, i) ) ( //函數體 (func, x, y, i=0) => ( i >= x.length ? null : x[i] == y ? i : func (func, x, y, i+1) ), //第一個調用參數 arr, //第二調用參數 2 //第三調用參數 ) ~~~ * 最后,引入高階函數,去除實參: ~~~javascript const find = ( highfunc => highfunc( highfunc ) ) ( func => (x, y, i = 0) => ( i >= x.length ? null : x[i] == y ? i : func (func) (x, y, i+1) ) ); ~~~ 注:函數式編程裝逼時一定要用const字符,這表示我寫的函數里的狀態是 immutable 的,天生驕傲! ## 4. 數組、字符串、對象及相互間的轉換 ### x.1 數組 ~~~javascript var arr=['nihao.ww',1]; console.log(arr[0]);//輸出:nihao.ww ~~~ ### x.2 字符串 ~~~javascript var str='nihao.ww'; console.log(str[0]);//輸出:n ~~~ ### x.3 對象 ~~~javascript var arr=['nihao.ww',1]; var str='nihao.ww'; var obj={arr,str}; //上述3行代碼可以合為: var obj={arr:['nihao.ww',1],str:'nihao.ww'}; //或 var obj={'arr':['nihao.ww',1],'str':'nihao.ww'}; console.log(obj.arr[0]);//輸出:nihao.ww console.log(obj.str[0]);//輸出:n ~~~ ### x.4 轉換 * 數組轉字符串 > toString()函數,無參數 ~~~javascript var arr=[1,'aaa',3]; var str=arr.toString(); var str=arr.toString(''); var str2=arr.toString('/+'); console.log(str);//輸出:1,aaa,3 console.log(str1);//輸出:1,aaa,3 console.log(str2);//輸出:1,aaa,3 ~~~ > join()函數,有參數 ~~~javascript var arr=[1,'aaa',3]; var str=arr.join(); var str1=arr.join(''); var str2=arr.join('/+'); console.log(str);//輸出:1,aaa,3 console.log(str1);//輸出:1aaa3 console.log(str2);//輸出:1/+aaa/+3 console.log(str[1]);//輸出:, console.log(str1[1]);//輸出:a console.log(str2[1]);//輸出:/ ~~~ * 字符串轉數組 > split()函數,有參數 ~~~javascript var str='nihao.ww'; var arr=str.split(); var arr1=str.split(''); var arr2=str.split('.'); console.log(arr);//輸出:["nihao.ww"] console.log(arr1);//輸出:["n", "i", "h", "a", "o", ".", "w", "w"] console.log(arr2);//輸出:["nihao","ww"] console.log(arr[0]);//輸出:nihao.ww console.log(arr1[0]);//輸出:n console.log(arr2[0]);//輸出:nihao ~~~ ## xx. 面向對象式編程(Object Orient Programming??)的編程范式 ## xx. 自調用匿名函數(javascript-self-invoking-functions) IIFE:immediately invoked function expressions?? 通常用于jQuery插件的開發?? 結構: ~~~javascript ;(function($,window,document,undefined){ //我們的代碼。。 //blah blah blah... })(jQuery,window,document); //箭頭函數的寫法 (() => 'foobar')(); ~~~ >[info] 可視為由2個'()'組成。 > 第一個'()',包含的是一個匿名函數。作用是定義函數。 > 第二個'()',包含的是要傳給匿名函數的參數,作用是將參數傳遞給定義好的函數并調用該函數。 JavaScript中無法用花括號方便地創建作用域,但函數卻可以形成一個作用域,域內的代碼是無法被外界訪問的。如上所示,用自調用匿名函數包裹代碼后的好處有: * 我們將自己的代碼放入一個函數中,就不會污染全局命名空間,同時不會和別的代碼沖突。 * 自調用匿名函數里面的代碼會在第一時間執行,頁面準備好后,上面的代碼就將插件準備好了,以方便在后面的代碼中使用插件。 * As soon as the function has been defined, it will immediately be called or invoked. I really like to use self invoking functions for doing initialization of things or adding event listeners or changing the layout of a page. In jQuery, usually a self invoked function was used instead of setting documment.ready * The primary benefit of self-invoking functions is that they execute only once and won’t fill the global namespace with all sorts of crud that lasts for the lifetime of the page. * It doesn’t seem like adding a few things to the global namespace would be a problm until you start getting into thousands of lines of javascript and having collisions between functions or variables. * Self invoking functions are commonly used for artificially creating namespaces which don’t natively exist in JavaScript. 代碼示例: ~~~javascript var $ = "some value we don't care about"; // v=====normal plain old function (function ($) { // ^=======receives jQuery object as the $ parameter //majority of code here, where $ === jQuery... $('.myclass').do().crazy().things(); })(jQuery); // ^=======immediately invoked, and passed the jQuery object // out here, $ is undisturbed alert( $ ); // "some value we don't care about" ~~~ you can call jQuery with the $() notation inside that function, and outside that function if something else like prototype uses $() notation it doesn't matter?.. So really it just saves you from having to write jQuery() (or some other notation) every time when using no conflict. Essentially everything, that is in the majority of code here ... bit, is isolated from the rest of the code. It exists in separate scope.The code outside this structure cannot overwrite anything that is inside. In javascript the $ symbol is just another variable. jQuery uses it because it is a nice shorthand instead of having to type out jQuery each time, but so can any other code (including other libraries). To prevent conflict with other uses of a variable at the same scope (in this case $ at the "global" scope) it is common for code to be wrapped in a self-invoking function with the "conflict-free" variables passed as the function parameters. This then creates a new scope where your variable won't interfere with other uses of that variable. That way you can pass the full named variable & uses it with whatever name you want within the anonymous function. ## Promise模式(異步編程) ### Promise.then [[MDN文檔,promise對象](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise)] ### async/await [[MDN文檔,async_function](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/async_function)] [[MDN文檔,await](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/await)] **描述** 當調用一個?`async`函數時,會返回一個`Promise`對象(Promise?對象用于表示一個異步操作的最終狀態(完成或失敗),以及其返回的值。)。當這個?`async`函數返回一個值時,`Promise`的 resolve 方法會負責傳遞這個值;當`async`函數拋出異常時,`Promise`的 reject 方法也會傳遞這個異常值。 `async`函數中可能會有`await`(await操作符用于等待一個Promise 對象。它只能在異步函數 async function 中使用。)表達式,這會使`async`函數暫停執行,等待?`Promise`? 的結果出來,然后恢復`async`函數的執行并返回解析值(resolved)。 ? ? 注意,?`await`?關鍵字僅僅在?`async`?function中有效。如果在?`async?function`函數體外使用?`await`?,只會得到一個語法錯誤。 `async`/`await`的用途是簡化使用 promises 異步調用的操作,并對一組?`Promises`執行某些操作。正如`Promises`類似于結構化回調,`async`/`await`類似于組合生成器和 promises。 若希望同時`await`兩個或者是更多的`Promise`對象,就必須使用`Promise.then`, ## 對象 在 Javascript 里,對象可以被看作是一組屬性的集合。用[對象字面量語法](https://developer.mozilla.org/en/JavaScript/Guide/Values,_variables,_and_literals#Object_literals)來定義一個對象時,會自動初始化一組屬性。 對象定義示例1 ~~~js var a = "Hello"; ~~~ a本身就會有a.substring這個方法,以及a.length這個屬性,以及其它; 對象定義示例2 ~~~js var a = {}; ~~~ a就會自動有a.hasOwnProperty及a.constructor等屬性和方法。 定義對象后,這些屬性還可以被增減。屬性的值可以是任意類型,包括具有復雜數據結構的對象。屬性使用鍵來標識,它的鍵值可以是一個字符串或者符號值(Symbol)。 ECMAScript定義的對象中有兩種屬性:數據屬性和訪問器屬性。 ### 數據屬性 數據屬性是鍵值對,并且每個數據屬性擁有下列特性: **數據屬性的特性(Attributes of a data property)** | 特性 | 數據類型 | 描述 | 默認值 | | --- | --- | --- | --- | | \[\[Value\]\] | 任何Javascript類型 | 包含這個屬性的數據值。 | undefined | | \[\[Writable\]\] | Boolean | 如果該值為?`false,`則該屬性的 \[\[Value\]\] 特性 不能被改變。 | true | | \[\[Enumerable\]\] | Boolean | 如果該值為?`true,`則該屬性可以用?[for...in](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in) 循環來枚舉。 | true | | \[\[Configurable\]\] | Boolean | 如果該值為?`false,`則該屬性不能被刪除,并且 除了 \[\[Value\]\] 和 \[\[Writable\]\] 以外的特性都不能被改變。 | true | ### 訪問器屬性 訪問器屬性有一個或兩個訪問器函數?(get 和 set) 來存取數值,并且有以下特性: 一個訪問器屬性的特性 | 特性 | 類型 | 描述 | 默認值 | | --- | --- | --- | --- | | \[\[Get\]\] | 函數對象或者 undefined | 該函數使用一個空的參數列表,能夠在有權訪問的情況下讀取屬性值。另見?[get](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/get)。 | undefined | | \[\[Set\]\] | 函數對象或者 undefined | 該函數有一個參數,用來寫入屬性值,另見?[set](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/set)。 | undefined | | \[\[Enumerable\]\] | Boolean | 如果該值為?`true`,則該屬性可以用?[for...in](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in)?循環來枚舉。 | true | | \[\[Configurable\]\] | Boolean | 如果該值為?`false`,則該屬性不能被刪除,并且不能被轉變成一個數據屬性。 | true | >[warning] 注意:這些特性只有 JavaScript 引擎才用到,因此你不能直接訪問它們。所以特性被放在兩對方括號中,而不是一對。 ### "標準的" 對象, 和函數 一個 Javascript 對象就是鍵和值之間的映射。鍵是一個字符串(或者[`symbol`](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Symbol "Symbol()函數會返回symbol類型的值,該類型具有靜態屬性和靜態方法。它的靜態屬性會暴露幾個內建的成員對象;它的靜態方法會暴露全局的symbol注冊,且類似于內建對象類,但作為構造函數來說它并不完整,因為它不支持語法:'new Symbol()'。")),值可以是任意類型的值。?這使得對象非常符合?[哈希表](http://en.wikipedia.org/wiki/Hash_table)。 函數是一個附帶可被調用功能的常規對象。 ### 日期 當你想要顯示日期時,毋庸置疑,使用內建的 [Date](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date) 對象。 ### 有序集: 數組和類型數組 [數組](https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array "Array")是一種使用整數作為鍵(integer-key-ed)屬性和長度(length)屬性之間關聯的常規對象。此外,數組對象還繼承了 Array.prototype 的一些操作數組的便捷方法。例如,?[`indexOf`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf "en/JavaScript/Reference/Global_Objects/Array/indexOf")?(搜索數組中的一個值) or?[`push`](https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/push "en/JavaScript/Reference/Global_Objects/Array/push")?(向數組中添加一個元素),等等。?這使得數組是表示列表或集合的最優選擇。 [類型數組(Typed Arrays)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays)是ECMAScript Edition 6中新定義的 JavaScript 內建對象,提供了一個基本的二進制數據緩沖區的類數組視圖。 ### 結構化數據: JSON JSON (JavaScript Object Notation) 是一種輕量級的數據交換格式,來源于 JavaScript 同時也被多種語言所使用。 JSON 用于構建通用的數據結構。參見 [JSON](https://developer.mozilla.org/en-US/docs/Glossary/JSON "JSON: JavaScript Object Notation?(JSON) is a data-interchange format.? Although not a strict subset, JSON closely resembles a subset of JavaScript syntax. Though many programming languages support JSON, JSON is especially useful for JavaScript-based apps, including websites and browser extensions.") 以及 [`JSON`](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/JSON "JSON對象包含兩個方法: 用于解析?JavaScript Object Notation? (JSON)?的 parse() 方法,以及將對象/值轉換為 JSON字符串的 stringify() 方法。除了這兩個方法, JSON這個對象本身并沒有其他作用,也不能被調用或者作為構造函數調用。") 了解更多。 JSON采用完全獨立于程序語言的文本格式,但是也使用了類C語言的習慣(包括C, C++, C#, Java, JavaScript, Perl, Python等)。這些特性使JSON成為理想的數據交換語言。 #### 1 JSON對象(object) 對象:對象在js中表示為“{}”括起來的內容,數據結構為 {key:value,key:value,...}的鍵值對的結構,在面向對象的語言中,key為對象的屬性,value為對應的屬性值。取值方法為 對象.key 獲取屬性值,這個屬性值的類型可以是 數字、字符串、數組、對象幾種。 ~~~JavaScript var val={"time":"2015-12-15 13:01:10","protocolVerion":"1.00","sensorId":"1234567890123456","signalValue":[{"D":"18.6","I1":"5","I2":"6","V1":"3.2","V2":"12","S1":"1","S2":"0","S3":"0","S4":"1","G":"112.23323,39.23434"}]} //將JSON對象轉化為JSON字符1 var last=obj.toJSONString(); //將JSON對象轉化為JSON字符2 var last=JSON.stringify(obj); //輸出 alert(last); ~~~ #### 2 JSON字符串(string) 是由單引號包圍的任意數量Unicode字符的集合,使用反斜線`\`轉義。 ~~~JavaScript var str1 = '{ "name": "cxh", "sex": "man" }'; //由JSON字符串轉換為JSON對象1 var obj = eval('(' + str + ')'); //由JSON字符串轉換為JSON對象2 var obj = str.parseJSON(); //由JSON字符串轉換為JSON對象3 var obj = JSON.parse(str); //讀取對象屬性 Alert(obj.name); Alert(obj.sex); ~~~ >[warning] 如果obj本來就是一個JSON對象,那么使用eval()函數轉換后(哪怕是多次轉換)還是JSON對象,但是使用parseJSON()函數處理后會有問題(拋出語法異常)。 ### 標準庫中更多的對象 JavaScript 有一個內置對象的標準庫。請查看[參考](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects)來了解更多對象。 ## 參考文檔 1. [《ECMAScript 6 入門》](http://es6.ruanyifeng.com/#README) 2. [[MDN文檔,JavaScript索引](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Index)] 3. [[MDN,Javascript]](https://developer.mozilla.org/en-US/docs/Web/JavaScript) ## XMLHttpRequest [[Living Standard](https://xhr.spec.whatwg.org)] The XMLHttpRequest Standard defines an API that provides scripted client functionality for transferring data between a client and a server. ## 待整理 所有函數的最外層被稱為全局作用域。 在全局作用域內定義的值可以在任意地方訪問。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看