av激情亚洲男人的天堂国语,日韩欧美精品一中文字幕,无码av一区二区三区无码,国产又色又爽又刺激的a片,国产又色又爽又刺激的a片

全棧必備JavaScript基礎(chǔ)

1995年,誕生了JavaScript語(yǔ)言,那一年,我剛剛從大學(xué)畢業(yè)。在今年RedMonk 推出的2017 年第一季度編程語(yǔ)言排行榜中,JavaScript 排第一,Java 第二,Python 反超 PHP 排第三,PHP 第四,C# 和 C++ 并列第五。RedMonk 排名的主要依舊是各種編程語(yǔ)言在 Stack Overflow 和 GitHub 上的表現(xiàn),比如編程語(yǔ)言在 Stack Overflow 上的討論數(shù)量,在 GitHub 上的代碼量等。盡管有一定的片面性,還是說(shuō)明了JavaScript 應(yīng)用的廣泛性。從全棧的角度看,Javascript 是必備的一種編程語(yǔ)言。

網(wǎng)站建設(shè)公司,為您提供網(wǎng)站建設(shè),網(wǎng)站制作,網(wǎng)頁(yè)設(shè)計(jì)及定制網(wǎng)站建設(shè)服務(wù),專(zhuān)注于企業(yè)網(wǎng)站設(shè)計(jì),高端網(wǎng)頁(yè)制作,對(duì)成都報(bào)廢汽車(chē)回收等多個(gè)行業(yè)擁有豐富的網(wǎng)站建設(shè)經(jīng)驗(yàn)的網(wǎng)站建設(shè)公司。專(zhuān)業(yè)網(wǎng)站設(shè)計(jì),網(wǎng)站優(yōu)化推廣哪家好,專(zhuān)業(yè)成都網(wǎng)站推廣優(yōu)化,H5建站,響應(yīng)式網(wǎng)站。

ECMAScript 和 JavaScript 的關(guān)系

JavaScript 誕生于Netscape,但是在1996年,微軟發(fā)布了與JavaScript 兼容的JScript,面對(duì)兼容和發(fā)展的需要,網(wǎng)景公司的先賢們努力加入了 ECMA International 標(biāo)準(zhǔn)化組織,致力于JavaScript 的標(biāo)準(zhǔn)化,命名為ECMAScript。后來(lái),由于歷史的原因, JavaScript標(biāo)準(zhǔn)的開(kāi)發(fā)主體變成了Mozila基金會(huì)。

簡(jiǎn)單地,ECMAScript 是JavaScript語(yǔ)言的標(biāo)準(zhǔn)規(guī)范,就像C++的標(biāo)準(zhǔn)相對(duì)于C++語(yǔ)言那樣。

JavaScript 是怎樣的語(yǔ)言

在mozilla 開(kāi)發(fā)者網(wǎng)站上是這樣描述JavaScript的:

JavaScript (JS) is a lightweight interpreted or JIT-compiled programming language with first-class functions.

意思是說(shuō)JavaScript 是一個(gè)輕量級(jí)解釋或即時(shí)編譯的函數(shù)式語(yǔ)言,里面有很多的概念,輕量、解釋、編譯、即時(shí)編譯、函數(shù)式。在老碼農(nóng)看來(lái),簡(jiǎn)單起見(jiàn),理解為擴(kuò)展語(yǔ)言較為方便。

一般的編程語(yǔ)言都有著自己相對(duì)獨(dú)立的執(zhí)行環(huán)境,但是JavaScript的執(zhí)行環(huán)境依賴(lài)在宿主環(huán)境中,宿主環(huán)境尤其是客戶(hù)端的宿主環(huán)境提供了更多統(tǒng)一的環(huán)境變量,比如瀏覽器中的window,document等。實(shí)際上,JavaScript 和DOM 是可分的,對(duì)于不同的運(yùn)行環(huán)境,有著不同的內(nèi)置宿主對(duì)象。JavaScript作為擴(kuò)展語(yǔ)言在內(nèi)置的宿主環(huán)境中運(yùn)行,全局對(duì)象在程序啟動(dòng)前就已經(jīng)存在了。

JavaScript的時(shí)空基礎(chǔ)

從空間觀(guān)的角度看,JavaScript包括數(shù)據(jù)結(jié)構(gòu),操作符,語(yǔ)句與表達(dá)式,函數(shù);從時(shí)間的角度看,包括作用域,處理方式,模塊與庫(kù)。

數(shù)據(jù)結(jié)構(gòu)

JavaScript 中包含的六種基本類(lèi)型:

  • Boolean
  • Null
  • Undefined
  • Number
  • String
  • Symbol (ECMAScript 6)

其它全是對(duì)象。值是有類(lèi)型的,變量是沒(méi)有類(lèi)型的,類(lèi)型定義了值的行為特征,變量在沒(méi)有持有值的時(shí)候是undefined。 JavaScript對(duì)值和引用的賦值/傳遞在語(yǔ)法上沒(méi)有區(qū)別,完全根據(jù)值的類(lèi)型來(lái)判定。

對(duì)于對(duì)象的屬性和方法而言,全局變量和全局函數(shù)是全局對(duì)象的屬性,全局對(duì)象相當(dāng)于宿主對(duì)象的根對(duì)象。需要注意是屬性的屬性中那些不可變對(duì)象的實(shí)現(xiàn)方式:

  1. 對(duì)象常量: 結(jié)合writable和configurable:false 可以創(chuàng)建一個(gè)真正的常量屬性
  2. 禁止擴(kuò)張:Object.preventExtensions(..)來(lái)禁止一個(gè)對(duì)象添加新屬性并保留已有屬性
  3. 密封: 在 Object.seal(..) 后不能增,刪,改 該屬性
  4. 凍結(jié): Object.freeze(..) 會(huì)禁止對(duì)于對(duì)象本身及任意直接屬性的修改

數(shù)據(jù)類(lèi)型的判定可以通過(guò) contructor,instanceof, isPrototypeOf等方法實(shí)現(xiàn),對(duì)于鴨子類(lèi)型的判定還可以使用 in 的相關(guān)操作。符號(hào)并非對(duì)象,而是一種簡(jiǎn)單標(biāo)量基本類(lèi)型。

JavaScript 中的強(qiáng)制類(lèi)型轉(zhuǎn)換總是返回基本類(lèi)型值,將對(duì)象強(qiáng)制轉(zhuǎn)換為String 是通過(guò)ToPrimitive抽象操作完成的,而toJSON()是返回一個(gè)能夠被字符串化的安全的JSON值。

操作符

操作符是空間元素連接的紐帶之一,JavaScript操作符包括算術(shù),連接,相等,比較,邏輯,位,類(lèi)型判斷,條件,new,delete, void,",", ".", "[]"等。

在JavaScript中以操作符進(jìn)行操作往往都附帶著類(lèi)型轉(zhuǎn)換。

一元運(yùn)算符+ 是顯式強(qiáng)制類(lèi)型轉(zhuǎn)換,而~是先轉(zhuǎn)換為32位數(shù)字,然后按位反轉(zhuǎn)。|| 和&& 更應(yīng)該算是選擇器運(yùn)算符,其返回值不一定是布爾值,而是兩個(gè)操作數(shù)其中的一個(gè)值。一般先對(duì)第一個(gè)操作數(shù)進(jìn)行toBoolean強(qiáng)制類(lèi)型轉(zhuǎn)換,然后再執(zhí)行條件判斷。例如:a||b 理解成a?a:b 更通俗。對(duì)&& 而言,如果第一個(gè)是真值,則把第二個(gè)作為返回值,a&&b 理解成a?b:a 。

== 和=== 都會(huì)對(duì)操作數(shù)進(jìn)行類(lèi)型檢查,并執(zhí)行隱性類(lèi)型轉(zhuǎn)換,需要注意的是:

  • 如果兩邊的值中有true或false,千萬(wàn)不要使用==
  • 如果兩邊有[],””或者0,盡量不要使用==

這里是Github上關(guān)于各種相等性的矩陣:

語(yǔ)句與表達(dá)式

操作符與變量/常量等連接形成了語(yǔ)句和表達(dá)式,例如表達(dá)式a+1中的null 被強(qiáng)制轉(zhuǎn)換為0。 語(yǔ)句包括聲明與塊,控制語(yǔ)句有判斷,循環(huán),break,continue,return,異常等。每個(gè)語(yǔ)句都有一個(gè)結(jié)果值,哪怕是undefined。

正則表達(dá)式是非常重要的一類(lèi)表達(dá)式,主要使用RegExp類(lèi),執(zhí)行方法test效率高,exec 會(huì)得到一個(gè)結(jié)果對(duì)象的數(shù)組。

逗號(hào)運(yùn)算符可以把多個(gè)獨(dú)立的表達(dá)式串聯(lián)成一個(gè)語(yǔ)句,{ }在不同情況下的意思不盡相同,作為語(yǔ)句塊,{ ..} 和for/while循環(huán)以及if條件語(yǔ)句中代碼塊的作用基本相同。{a,b} 實(shí)際上是{a:a,b:b}的簡(jiǎn)化版本。

try..catch..finally 中,如果finally中拋出異常,函數(shù)會(huì)在此處終止。需要注意的是,如果此前try中已經(jīng)有return設(shè)置了返回值,則該值會(huì)被丟棄。finally中的return也會(huì)覆蓋try和catch中的return的返回值。

函數(shù)與作用域

函數(shù)就是具有運(yùn)算邏輯的對(duì)象,匿名函數(shù)不利于調(diào)試,回調(diào)函數(shù)是一種控制反轉(zhuǎn)。所有的函數(shù)(對(duì)象)都具有名為prototype的屬性,prototype屬性引用的對(duì)象是prototype對(duì)象;所有的對(duì)象都含有一個(gè)隱式鏈接,用以指向在對(duì)象生成過(guò)程中所使用的構(gòu)造函數(shù)的prototype對(duì)象。

匿名函數(shù)沒(méi)有name 標(biāo)識(shí)符,具有如下缺陷:

  1. 代碼更難理解
  2. 調(diào)試棧更難追蹤
  3. 自我引用(遞歸,事件(解除)綁定,等)更難

如果function是聲明的第一個(gè)詞,那就是函數(shù)聲明,否則就是函數(shù)表達(dá)式。立即執(zhí)行函數(shù)表達(dá)式形如:(function …)( )

時(shí)空密不可分,作用域是時(shí)空連接的紐帶之一。作用域包括全局,函數(shù),塊級(jí)作用域。作用域是根據(jù)名稱(chēng)查找變量的一套規(guī)則,遍歷嵌套作用域鏈的規(guī)則簡(jiǎn)單:引擎從當(dāng)前執(zhí)行作用域逐級(jí)向上查找。閉包可以理解為具有狀態(tài)的函數(shù)。

函數(shù)作用域指屬于這個(gè)函數(shù)的全部變量都可以在整個(gè)函數(shù)的范圍內(nèi)使用或復(fù)用。塊作用域形如 with, try/catch, ES6 引入了let,const等。

動(dòng)態(tài)作用域并不關(guān)心函數(shù)和作用域是如何聲明以及在何處聲明的,只關(guān)心它們從何處調(diào)用的。詞法作用域是定義在詞法分析階段的作用域,詞法作用域查找會(huì)在第一個(gè)匹配的標(biāo)識(shí)符時(shí)停止。作用域鏈?zhǔn)腔谡{(diào)用棧的,而不是代碼中的作用域嵌套。ReferenceError 是與作用域判別失敗相關(guān),而TypeError則是作用域判別成功,但是對(duì)結(jié)果的操作非法或不合理。

this 提供了一種優(yōu)雅方式來(lái)隱式“傳遞”一個(gè)對(duì)象引用。 this 即沒(méi)有指向函數(shù)的自身,也沒(méi)有指向函數(shù)的作用域,是在函數(shù)被調(diào)用時(shí)發(fā)生的綁定,它指向什么完全取決于函數(shù)在哪里被調(diào)用。如果分析this綁定的話(huà),可以使用調(diào)試工具得到調(diào)用棧,然后找到棧中的第二個(gè)元素,就是真正的調(diào)用位置。

this 的綁定規(guī)則有:

  1. 默認(rèn)綁定:獨(dú)立的函數(shù)調(diào)用,嚴(yán)格模式不能將全局對(duì)象用于默認(rèn)綁定
  2. 隱式綁定:把函數(shù)調(diào)用中的this 綁定到函數(shù)引用中的上下文對(duì)象
  3. 顯式綁定:通過(guò)call()和apply()方法可以直接指定this的綁定對(duì)象。其中,硬綁定是一種顯式的強(qiáng)制綁定,ES5中提供了內(nèi)置方法Function.prototype.bind, API中調(diào)用的上下文和bind的作用一樣。
  4. new 綁定,構(gòu)造函數(shù)只是一些使用new操作符調(diào)用的函, 使用new 來(lái)調(diào)用函數(shù)的操作過(guò)程大致如下:
  • 創(chuàng)建一個(gè)全新的對(duì)象
  • 這個(gè)新對(duì)象會(huì)被執(zhí)行[[Prototype]]鏈接
  • 這個(gè)新對(duì)象會(huì)綁定到函數(shù)調(diào)用的this
  • 如果函數(shù)沒(méi)有返回其他對(duì)象,那么new表達(dá)式中的函數(shù)調(diào)用會(huì)自動(dòng)返回這個(gè)新對(duì)象

如果同時(shí)存在多種綁定,那么綁定的優(yōu)先級(jí)大致如下:

  1. 由new調(diào)用綁定到新創(chuàng)建的對(duì)象
  2. 由call 或者apply(或bind)調(diào)用綁定到指定的對(duì)象
  3. 由上下文對(duì)象調(diào)用綁定到那個(gè)上下文對(duì)象
  4. 默認(rèn)在在嚴(yán)格模式下綁定到undefined,否則綁定到全局對(duì)象

更安全地使用this 綁定的做法是傳入一個(gè)特殊的對(duì)象,把this 綁定到這個(gè)對(duì)象。需要注意的是,箭頭函數(shù)不使用this的4種規(guī)則,而是根據(jù)外層(函數(shù)或全局)作用域來(lái)決定this。

還要注意一點(diǎn),eval 和 with 會(huì)導(dǎo)致作用域變化而引起性能下降,盡量不要使用。eval() 函數(shù)中的字符串是代碼,用來(lái)執(zhí)行動(dòng)態(tài)創(chuàng)建的代碼,嚴(yán)格模式有自己的作用域,還存在安全隱患;with 是重復(fù)引用一個(gè)對(duì)象中的多個(gè)屬性的快捷方式,通過(guò)將一個(gè)對(duì)象的引用當(dāng)作作用域來(lái)處理,會(huì)改變作用域范圍。

處理和執(zhí)行方式

JavaScript引擎本身沒(méi)有時(shí)間概念,只是一個(gè)按需執(zhí)行任意代碼片段的環(huán)境,事件調(diào)度總是由包含它的宿主環(huán)境來(lái)執(zhí)行。一旦有事件需要運(yùn)行,事件循環(huán)隊(duì)列就會(huì)運(yùn)行,直到隊(duì)列清空,用戶(hù)交互、IO和定時(shí)器等事件源會(huì)向事件隊(duì)列加入事件。

由于JavaScript的單線(xiàn)程特性,很多函數(shù)的代碼具有原子性。

回調(diào)函數(shù)封裝了程序的延續(xù)性,常見(jiàn)設(shè)計(jì)是分離回調(diào)(一個(gè)用于成功通知,一個(gè)用于出錯(cuò)通知)。另一種回調(diào)模式是“error-first”,可能受到防御式編程的影響,NodeJS API 采用了此類(lèi)的風(fēng)格,如果成功的話(huà),這個(gè)參數(shù)就會(huì)被清空。需要注意的是,回調(diào)函數(shù)的嵌套往往稱(chēng)為回調(diào)地獄。

Deferred是一種將異步處理串聯(lián)書(shū)寫(xiě)并執(zhí)行的機(jī)制,Deferred對(duì)象是一種具有unresolved,resolved,rejected 中某一種狀態(tài)的對(duì)象。Deferred內(nèi)部機(jī)制是先注冊(cè)回調(diào)函數(shù),Deferred對(duì)象狀態(tài)發(fā)生變化時(shí)執(zhí)行該函數(shù),是一種提高代碼可讀性的機(jī)制。

Deferred對(duì)象的狀態(tài)遷移只能發(fā)生一次,以then(),done(),fail(),always(),pipe()指定后續(xù)函數(shù)的方法,通過(guò)when()來(lái)并行處理,將Deferred 對(duì)象中的一部分方法刪除后得到是Promise對(duì)象,對(duì)狀態(tài)的管理由最初創(chuàng)建該Deferred對(duì)象的所有者來(lái)執(zhí)行。

Promise 封裝了依賴(lài)于時(shí)間的狀態(tài),從而使得本身與時(shí)間無(wú)關(guān),Promise 可以按照可預(yù)測(cè)的方式進(jìn)行,而不用關(guān)心時(shí)序或底層的結(jié)果。一旦Promise決議完成,就成為了不變值,可以安全地吧這個(gè)值傳遞給第三方,并確保不會(huì)改變。

Promise 是一種在異步任務(wù)中作為兩個(gè)或更多步驟的流程控制機(jī)制,時(shí)序上的this-then-that。 不僅表達(dá)了多步異步序列的流程控制,還是一個(gè)從一個(gè)步驟到下一個(gè)步驟傳遞消息的消息通道。事件監(jiān)聽(tīng)對(duì)象可以當(dāng)成是對(duì)promise 的一種模擬,對(duì)控制反轉(zhuǎn)的恢復(fù)實(shí)現(xiàn)了更好的關(guān)注點(diǎn)分離。

判斷是否是Promise 值的示例代碼如下:

 
 
 
 
  1. if(
  2.     p !==null &&
  3.     ( typeof p ===“object” || typeof p ===“function”) && typeof p.then===“function”)
  4.     {
  5.         console.log(“thenable”);
  6.     }
  7. else{
  8.     console.log(“not thenable”);
  9. }

生成器是一類(lèi)特殊的函數(shù),可以一次或多次啟動(dòng)和停止,并不非的一定要完成,生成器把while true 帶回了Javascript的世界。其中,yield 委托的主要目的是代碼組織,以達(dá)到與普通函數(shù)調(diào)用的對(duì)稱(chēng)。從生成器yield出一個(gè)Promise, 并且讓這個(gè)Promise 通過(guò)一個(gè)輔助函數(shù)恢復(fù)這個(gè)生成器,這是通過(guò)生成器管理異步的好方法之一。

需要注意的是,如果在Promise.all([..]) 中傳入空數(shù)組,會(huì)立即完成, 而Promise.race([..]) 則會(huì)掛住。 在各種Promise庫(kù)中,finally ( .. ) 還是會(huì)創(chuàng)建并返回一個(gè)新Promise的。

模塊與庫(kù)

模塊和庫(kù)是JavaScript 時(shí)空中的另一紐帶,提高了代碼的復(fù)用性和開(kāi)發(fā)效率。

模塊充分利用了閉包的強(qiáng)大能力,從模塊中返回一個(gè)實(shí)際的對(duì)象并不是必須的,也可以直接返回一個(gè)內(nèi)部函數(shù),例如:jQauery 和 $標(biāo)識(shí)符就是jQuery 模塊的公共API。

模塊有兩個(gè)必要條件:

  1. 必須有外部的封閉函數(shù),該函數(shù)必須至少被調(diào)用一次
  2. 封閉函數(shù)必須返回至少一個(gè)內(nèi)部函數(shù),這樣內(nèi)部函數(shù)才能在私有作用域中形成閉包,并且可以訪(fǎng)問(wèn)或修改私有的狀態(tài)

import 可以將一個(gè)模塊的一個(gè)或多個(gè)API導(dǎo)入到當(dāng)前作用域中,并分別綁定在一個(gè)變量上;module 則將整個(gè)模塊的API 導(dǎo)入并綁定到一個(gè)變量上, export 將當(dāng)前模塊的一個(gè)標(biāo)識(shí)符導(dǎo)出為公共API。

大多數(shù)模塊所依賴(lài)的加載器/管理器本質(zhì)上是將這種模塊定義封裝進(jìn)一個(gè)API?;诤瘮?shù)的模塊并不是一個(gè)能被靜態(tài)識(shí)別的模式(編譯器),API定義只有在運(yùn)行時(shí)考慮進(jìn)來(lái)。但是ES6 模塊的API 是靜態(tài)的,必須被定義在獨(dú)立的文件中。

JavaScript 中的庫(kù)浩如煙海,這里僅對(duì)JQuery做簡(jiǎn)要說(shuō)明。JQuery壓縮后大約31k,輕巧靈活,通過(guò)鏈?zhǔn)秸Z(yǔ)法實(shí)現(xiàn)邏輯功能,通過(guò)CSS3選擇器及自定義選擇器獲取元素,支持插件,可擴(kuò)展性高。

JQuery中 的特色函數(shù)——$ ,可以抽取與選擇器匹配的元素,或者創(chuàng)建新的DOM元素,將已有的DOM元素轉(zhuǎn)換為jQuery對(duì)象,對(duì)DOM構(gòu)造完成后的事件監(jiān)聽(tīng)器進(jìn)行設(shè)定等等。JQuery 對(duì)DOM,樣式,AJAX 均可有效處理。

通過(guò)擴(kuò)展JQuery.fn 就可以創(chuàng)建JQuery的插件,code.google.com/apis/libraries 給出了很多JQuery 的插件信息。

利用JavaScript 的時(shí)空觀(guān),可以對(duì)這一語(yǔ)言有一些基本的梳理。就語(yǔ)言本身而言,關(guān)鍵字是不能回避的,對(duì)JavaScript 關(guān)鍵字,在StackOverFlow中有人給出了如下詩(shī)一樣的總結(jié):

 
 
 
 
  1. Let this long package float,
  2. Goto private class if short。
  3. While protected with debug case,
  4. Continue volatile interface。
  5. Instanceof super synchronized throw,
  6. Extends final export throws.
  7. Try import double enum?
  8. -False, boolean, abstract function.
  9. Implements typeof transient break!
  10. Void static,default do,
  11. Switch int native new,
  12. else, delete null public var,
  13. In return for const, true, char,
  14. …… finally catch byte.

客戶(hù)端應(yīng)用

一門(mén)語(yǔ)言所被使用的廣泛程度取決于使用的場(chǎng)景,正如PHP被廣泛采用那樣,互聯(lián)網(wǎng)應(yīng)用不僅是JavaScript 的家鄉(xiāng),而且是它大展身手的最重要場(chǎng)所,沒(méi)有JavaScript 的Web應(yīng)用幾乎絕跡了。

web應(yīng)用中使用JavaScript有拖拽操作,異步讀取,鍵盤(pán)訪(fǎng)問(wèn) 和動(dòng)畫(huà)效果等基本功能。對(duì)于清晰地使用JavaScript實(shí)現(xiàn)Web應(yīng)用而言,理解瀏覽器網(wǎng)頁(yè)處理過(guò)程是必要的。一般地,瀏覽器先分析HTML,然后構(gòu)造DOM樹(shù),再載入外部Javascript 文件以及CSS文件,接下來(lái)載入圖像文件等外部資源,最后在分析Javascript后開(kāi)始執(zhí)行至全部完成。

在HTML中加載JavaScript的方式有多種:

  • DataTransfer 是Drag Drop API 的核心,在所有拖拽事件的事件對(duì)象中,都有該屬性,主要是接收數(shù)據(jù)。拖拽文件從瀏覽器保存到桌面:event.dataTransfer.setData(‘DownloadURL’,’MIMETYPE: 文件url’)例如:

     
     
     
     
    1.    data-downloadurl = “application/pdf:abel.pdf:http://a.b.c/abel.pdf”
    2.    class=“dragout” draggable = “true”>download 
    3.    

    FileAPI 通過(guò)FileReader 讀取文件,也可以讀取dataURL,F(xiàn)ileReaderSync 用于同步讀取文件內(nèi)容,可以在Web Worker 中使用。

    Web Storage 為所有源共享5M空間,localStorage 和sessionStorage 的區(qū)別在于數(shù)據(jù)的生命周期。cookie 最大4k,發(fā)請(qǐng)求時(shí)一起發(fā)送,保存會(huì)話(huà)等重要信息。indexedDB 可以歸為文檔型數(shù)據(jù)庫(kù), 作為客戶(hù)端存儲(chǔ)又一選擇。

     
     
     
     
    1. var indexdb = window.indexDB||window.webkitIndexedDB||window.mozIndexedDB;

    Web worker 是H5 的新特性,是宿主環(huán)境(瀏覽器)的功能,JavaScript 本身是不支持多線(xiàn)程的。專(zhuān)用的worker 與創(chuàng)建它的程序之間是一對(duì)一的關(guān)系。

    Web worker 能在另外的線(xiàn)程中創(chuàng)建新的Javascript 運(yùn)行環(huán)境,使JavaScripts可以在后臺(tái)處理。主線(xiàn)程和工作線(xiàn)程分離,無(wú)法使用對(duì)方環(huán)境的變量。工作線(xiàn)程無(wú)法引用document對(duì)象,需要通過(guò)消息收發(fā)完成數(shù)據(jù)傳遞。 在主線(xiàn)程創(chuàng)建工作線(xiàn)程,大約向var worker = new Worker(‘work.js’)這樣 在主線(xiàn)程中停止worker的方式是worker.terminate(); worker 自身停止的方式是 self.close();worker 中 可以通個(gè) importScripts 方法,在工作線(xiàn)程內(nèi)讀取外部的文件。

    了解了這些基礎(chǔ)方式和方法,僅僅是Web應(yīng)用中JavaScript開(kāi)發(fā)的第一步吧。

    服務(wù)端應(yīng)用

    技術(shù)系統(tǒng)總是又著向超系統(tǒng)進(jìn)化的趨勢(shì),JavaScript 也不例外。

    JavaScript 應(yīng)用于服務(wù)端的開(kāi)發(fā)源于2009年初出現(xiàn)的CommonJS,后來(lái)成為為了服務(wù)器端javaScript的規(guī)范。基于JavaScript沒(méi)有模塊系統(tǒng)、標(biāo)準(zhǔn)庫(kù)較少、缺乏包管理工具等現(xiàn)狀,CommonJS規(guī)范希望JavaScript可以在任何地方運(yùn)行,以達(dá)到Java、C#、PHP這些后臺(tái)語(yǔ)言具備開(kāi)發(fā)大型應(yīng)用的能力。CommonJS是一種思想,它的終極目標(biāo)是使應(yīng)用程序開(kāi)發(fā)者根據(jù)CommonJS API編寫(xiě)的JavaScript應(yīng)用可以在不同的JavaScript解析器和HOST環(huán)境上運(yùn)行,例如編寫(xiě)服務(wù)端應(yīng)用,命令行工具,基于GUI的桌面應(yīng)用和混合應(yīng)用編程等,詳情參加 www.commonjs.org 。

    NodeJS可以理解成CommonJS規(guī)范的一種實(shí)現(xiàn),而且是部分實(shí)現(xiàn)。NodeJS以V8作為JavaScript的實(shí)現(xiàn)引擎,通用的異步處理事件循環(huán),提供了一系列非阻塞函數(shù)庫(kù)來(lái)支持實(shí)踐循環(huán)特性。同時(shí),NodeJS提供了高度優(yōu)化的應(yīng)用庫(kù),來(lái)提高服務(wù)器效率,例如其http 模塊是為快速非阻塞式http服務(wù)而用C語(yǔ)言重寫(xiě)的。另外,NodeJS還有shell的命令行工具,通過(guò)包系統(tǒng)實(shí)現(xiàn)擴(kuò)展,擴(kuò)展列表可以詳情參見(jiàn): GitHub.com/node/wiki/modules。

    JavaScript 中的主要實(shí)現(xiàn)引擎包括:IE采用的JScript,F(xiàn)irefox采用的SpiderMoneky,Chrome 采用的V8,Safari采用的webkit中的 javacriptcore燈。如果要對(duì)引擎有進(jìn)一步的了解,可以研讀一下javascriptcore等相關(guān)的源代碼。

    V8 是NodeJS 中的核心引擎,NodeJS的系統(tǒng)架構(gòu)大致如下:

    與瀏覽器相對(duì)應(yīng),Node 中的全局變量可以通過(guò) Object.keys(global); 獲得, 看一看NodeJS中的 “hello world” 程序:

     
     
     
     
    1. var http = require('http');
    2. http.createServer(function (req,res){
    3.     res.writeHead(200,{'Content-type':'text/plain'});
    4.     res.end('Hello Node.js \n');
    5. }).listen(1234,"127.0.0.1");
    6. console.log('Server running on http://127.0.0.1:1234/');

    幾行代碼就實(shí)現(xiàn)一個(gè)簡(jiǎn)單web server, 使Pythoner 們聯(lián)想到了 Tornado, 它們都走在單線(xiàn)程異步IO的路上。

    NodeJS 提供了對(duì)https 的支持,可以通過(guò)openssl 生成證書(shū)的方式大致是:

     
     
     
     
    1. openssl req -new -x509 -keyout key.pen -out cert.perm

    使用證書(shū)的示例如下:

     
     
     
     
    1. var fs  =require(‘fs’);
    2. var options = {
    3.     key: fs.readFileSync(‘key.perm’);
    4.     cert:fs.readFileSync(‘cert.perm’);
    5. }

    NodeJS支持socket 和文件處理,配合系統(tǒng)擴(kuò)展可以使用各種模版語(yǔ)言?;贜odeJS的實(shí)際在業(yè)界非常廣泛,比如面向websocket的IM系統(tǒng),各種web應(yīng)用網(wǎng)站等等。

    鑒于微服務(wù)架構(gòu)的興起,也誕生了基于Node的微服務(wù)架構(gòu)——Seneca,它使用完備的模式匹配接口來(lái)連接各個(gè)服務(wù),從代碼中將數(shù)據(jù)傳輸抽象出來(lái),使編寫(xiě)具有高擴(kuò)展性的軟件變得相當(dāng)容易。Seneca 沒(méi)有使用依賴(lài)注入,但是在處理控制反轉(zhuǎn)上相當(dāng)靈活,沒(méi)有關(guān)鍵字和強(qiáng)制的字段,只需一組鍵值對(duì),用于模式匹配的引擎中。具體參考實(shí)現(xiàn),可以參考《node.js 微服務(wù)》一書(shū)。

    基于JavaScript的全棧

    如果在整個(gè)應(yīng)用系統(tǒng)中主要使用JavaScript編程語(yǔ)言作為技術(shù)棧,那么也可以成為基于JavaScript 的全棧,關(guān)于全棧的論述可以參加《全棧的技術(shù)棧設(shè)想》和《再談< 全棧架構(gòu)師>》兩篇文字。例如MEAN架構(gòu),即MongoDB + Express + Angular + Node,MEAN 技術(shù)棧代表著一種完全現(xiàn)代的 Web 開(kāi)發(fā)方法:一種語(yǔ)言運(yùn)行在應(yīng)用程序的所有層次上,從客戶(hù)端到服務(wù)器,再到持久層。借助JavaScript的測(cè)試框架,比如MochaJS、JasmineJS 和 KarmaJS,可以為自己的 MEAN 應(yīng)用程序編寫(xiě)深入而又全面的測(cè)試套件,據(jù)說(shuō)MEAN有取代LAMP/LNMP的的趨勢(shì),但還需保持謹(jǐn)慎。

    引擎的差異

    正像Java 那樣,盡管又著虛擬機(jī)規(guī)范,但各個(gè)JVM的實(shí)現(xiàn)還是有著些許的不同,JavaScript 也是如此。JavaScript各引擎中同樣存在著少量的限制,例如:

    • 字符串常量中允許的最大字符數(shù)
    • 作為參數(shù)傳遞到函數(shù)中的數(shù)據(jù)大小(棧大小)
    • 函數(shù)聲明中的參數(shù)個(gè)數(shù)
    • 函數(shù)調(diào)用鏈的最大長(zhǎng)度
    • 以阻塞方式在瀏覽器中運(yùn)行的最大時(shí)間
    • 變量名的最大長(zhǎng)度
    • 盡管如此,JavaScript 在瀏覽器中的表現(xiàn)還是基本上可信的。

    從軟件到硬件

    實(shí)際上,JavaScript已經(jīng)嵌入到了從機(jī)器人到各種家電等各種各樣的設(shè)備中。這里隆重推薦我非常敬佩的好友——周愛(ài)民老師,他在Ruff(南潮信息科技)做的事情就是JavaScript 在物聯(lián)網(wǎng)上的進(jìn)一步應(yīng)用。

    Ruff 是一個(gè)可以讓開(kāi)發(fā)者實(shí)現(xiàn)敏捷開(kāi)發(fā)智能硬件的系統(tǒng)平臺(tái)。它包含了Ruff SDK、Ruff OS,Rap Registry等。從技術(shù)上講,Ruff 是一個(gè) JavaScript 運(yùn)行時(shí),專(zhuān)為硬件開(kāi)發(fā)而設(shè)計(jì)。Ruff 對(duì)硬件進(jìn)行了抽象,使用了基于事件驅(qū)動(dòng)、異步 I/O 的模型,使硬件開(kāi)發(fā)變得輕量而且高效。硬件抽象層,使得操作硬件猶如普通程序庫(kù),降低了硬件領(lǐng)域進(jìn)入門(mén)檻。

    Ruff 為開(kāi)發(fā)者提供了完善的開(kāi)發(fā)服務(wù)。從項(xiàng)目生產(chǎn)、軟件包管理、應(yīng)用管理、外設(shè)管理到固件管理等一系列現(xiàn)代軟件開(kāi)發(fā)方式,PC 端完成開(kāi)發(fā),無(wú)需燒板子,提升開(kāi)發(fā)者的開(kāi)發(fā)效率。Ruff 還提供了完善的測(cè)試框架,支持 assert、test、mock 等模塊,在開(kāi)發(fā)機(jī)上測(cè)試邏輯,硬件測(cè)試也能 TDD。

    官網(wǎng)(ruff.io) 上給出的示例如下:

     
     
     
     
    1. $.ready(function() {
    2.    $('#led-0').turnOn();
    3. });

    打開(kāi)電路板上的一個(gè)LED 燈,就是如此的簡(jiǎn)單。目前,一個(gè) Ruff 硬件同時(shí)只能運(yùn)行一款 Ruff 應(yīng)用,它將擁有自己獨(dú)立的進(jìn)程,著可能也受到JavaScript自身的限制吧。

    關(guān)注性能

    性能是全棧關(guān)注的一個(gè)重要維度,那句“過(guò)早優(yōu)化是萬(wàn)惡之源”實(shí)際上是我們對(duì)高德納先生的斷章取義,原文是這樣的:

    我們應(yīng)該在例如97%的時(shí)間里,忘掉小處的效率;過(guò)早優(yōu)化是萬(wàn)惡之源。但我們不應(yīng)該錯(cuò)過(guò)關(guān)鍵的3%中的機(jī)會(huì)。

    實(shí)際上是非關(guān)鍵路徑上的優(yōu)化是萬(wàn)惡之源,問(wèn)題在于如何確定我們的代碼是否在關(guān)鍵路徑上。不論節(jié)省的時(shí)間多么少,花費(fèi)在關(guān)鍵路徑上的性能優(yōu)化都是值得的。

    對(duì)于性能優(yōu)化工具,用于JavaScript源代碼壓縮有 google Closure complier,packer,YUI compressor,JSmin等。頁(yè)面的性能優(yōu)化工具有YSlow 和Page Speed等。實(shí)際上,任何有意義且可靠的性能測(cè)試都是基于統(tǒng)計(jì)學(xué)上的合理實(shí)踐。 就JavaScript 代碼本身的性能而言,benchmarkjs 是一個(gè)很好的工具,而jsperf.com 提供了對(duì)JavaScript 執(zhí)行環(huán)境的性能測(cè)試。

    總之,JavaScript 是一個(gè)具有強(qiáng)大生命力的語(yǔ)言,前端框架更是日新月異,從Angular,Vue,到React, 乃至React Native,給人以目不暇接的感覺(jué),但是,老碼農(nóng)覺(jué)得基礎(chǔ)認(rèn)識(shí)還是非常必要的,勿在浮沙筑高塔。

    【本文來(lái)自專(zhuān)欄作者“老曹”的原創(chuàng)文章,作者微信公眾號(hào):喔家ArchiSelf,id:wrieless-com】


    本文標(biāo)題:全棧必備JavaScript基礎(chǔ)
    本文來(lái)源:http://uogjgqi.cn/article/dhchsjs.html
掃二維碼與項(xiàng)目經(jīng)理溝通

我們?cè)谖⑿派?4小時(shí)期待你的聲音

解答本文疑問(wèn)/技術(shù)咨詢(xún)/運(yùn)營(yíng)咨詢(xún)/技術(shù)建議/互聯(lián)網(wǎng)交流