Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
SS是如何運(yùn)行的?他到底是怎么工作的,如何從CSS應(yīng)用到DOM,今天和大家分享下!
知識(shí)分類(lèi) | 基礎(chǔ)計(jì)算機(jī)知識(shí)、基礎(chǔ)軟件安裝、簡(jiǎn)單文件知識(shí)、HTML基礎(chǔ)知識(shí) |
目 標(biāo) | 理解瀏覽器如何加載CSS和HTML、瀏覽器遇到無(wú)法解析的CSS會(huì)發(fā)生什么 |
原 因 | 在一些面試場(chǎng)合,也會(huì)因?yàn)镃SS原理會(huì)問(wèn)到 |
當(dāng)設(shè)備一個(gè)文件的時(shí)候,必須符合文件的內(nèi)容文件的樣式信息,下面我們會(huì)處理它的標(biāo)準(zhǔn)文件的樣式信息,是,下面的步驟是加載網(wǎng)頁(yè)的需要瀏覽的版本,展示它的版本。瀏覽器并且在處理文件的時(shí)候會(huì)有不同的方式,但是下面的步驟基本都會(huì)出現(xiàn)。
結(jié)合下面的圖示更形象:
一個(gè)DOM有一個(gè)樹(shù)形文字結(jié)構(gòu),標(biāo)注語(yǔ)言中的每個(gè)元素、屬性以及每一段都著結(jié)構(gòu)樹(shù)中的節(jié)點(diǎn)(Node/DOM或DOM node)。節(jié)點(diǎn)由一個(gè)節(jié)點(diǎn)本身和其他DOM節(jié)點(diǎn)的關(guān)系定義,有些有父節(jié)點(diǎn),有些節(jié)點(diǎn)有兄弟節(jié)點(diǎn)(同級(jí))。
對(duì)于DOM的理解操作會(huì)幫助你設(shè)計(jì)、調(diào)試和維護(hù)你的CSS,因?yàn)镈OM是你的CSS樣式和文件內(nèi)容的部分。當(dāng)你瀏覽器F12調(diào)試的時(shí)候你需要DOM以查看使用了哪些規(guī)則。
很長(zhǎng)且枯燥的案例,這里我們通過(guò)一個(gè)HTML片段來(lái)了解HTML如何轉(zhuǎn)換成DOM
下面列HTML代碼:當(dāng)前
在這個(gè) DOM 中,<p>元素的節(jié)點(diǎn)是父節(jié)點(diǎn),它的子節(jié)點(diǎn)是一個(gè)文本節(jié)點(diǎn)和三個(gè)節(jié)點(diǎn)節(jié)點(diǎn)<span>的節(jié)點(diǎn)節(jié)點(diǎn),SPAN同時(shí)也是他們的文本節(jié)點(diǎn)的父節(jié)點(diǎn)。
上圖就是瀏覽器怎么解析之前的那個(gè)HTML片段——它生成上圖的DOM樹(shù)形結(jié)構(gòu),然后按照輸出到瀏覽器:
讓我們看看添加一些CSS到文件里渲染,同樣的HTML代碼:
下面為CSS代碼:
瀏覽器會(huì)解析HTML并創(chuàng)建一個(gè)DOM,然后解析CSS??梢钥吹轿ㄒ坏倪x擇器就是span元素選擇器,瀏覽器處理規(guī)則會(huì)非常快!把同樣的規(guī)則用在三個(gè)<span>標(biāo)簽上,然后直接渲染出圖像到屏幕上。
現(xiàn)在的顯示如下:
在的文章中提到了并不會(huì)實(shí)現(xiàn)所有的瀏覽器,很多人也不會(huì)實(shí)現(xiàn)最新的瀏覽器的文章,因此我們可以同時(shí)使用 CSS 持續(xù)不斷地開(kāi)發(fā)之前的領(lǐng)先瀏覽器,你可能會(huì)宣布奇怪的選擇器遇到無(wú)法解析的 CSS 器或何時(shí)會(huì)發(fā)生瀏覽?
答案就是瀏覽器什么也不會(huì)做,繼續(xù)解析下一個(gè)CSS樣式!
如果這些瀏覽器在解析你所寫(xiě)的 CSS 規(guī)則制定的過(guò)程中遇到了無(wú)法理解的屬性或值,它會(huì)顯示并繼續(xù)解析 CSS 聲明?;蛘弋?dāng)瀏覽器遇到它很新的時(shí)候還沒(méi)有支持的 CSS 代碼的時(shí)候上面的情況同樣會(huì)發(fā)生(觸發(fā))。
類(lèi)似的,當(dāng)遇到無(wú)法解析選擇器的時(shí)間時(shí),他會(huì)直接啟動(dòng)整個(gè)選擇器規(guī)則,解析下一個(gè) CSS 選擇器。
下面的案例中,我使用會(huì)導(dǎo)致錯(cuò)誤的英式拼寫(xiě)來(lái)寫(xiě)“顏色”,所以我的屬性的段落沒(méi)有被渲染成藍(lán)色,而執(zhí)行其他的CSS代碼會(huì)正常,只有錯(cuò)誤的部分會(huì)被觸發(fā)。
瀏覽器瀏覽中多,代表著你使用最新的 CSS 優(yōu)化過(guò)程中的一個(gè)無(wú)法解析的規(guī)則也不會(huì)報(bào)錯(cuò)。當(dāng)你瀏覽多個(gè) CSS 樣式的時(shí)候,會(huì)加載樣式表中指定的元素最后的 CSS 代碼進(jìn)行渲染多個(gè)樣式表,上級(jí)請(qǐng)同一個(gè)指定的樣式表,正因?yàn)檫@樣,你來(lái)解決一些瀏覽器等瀏覽器也不能為新特性的問(wèn)題(比如指定兩個(gè) CSS 樣式)個(gè)width)。
這個(gè)特點(diǎn)在你想的一個(gè)很新的 CSS 特性,但不是所有的瀏覽器都支持使用的時(shí)候(瀏覽器)非常有用,更有意義,一些老的瀏覽器不接受calc()(計(jì)算一下,CSS3 新增,作為元素動(dòng)態(tài)寬度、長(zhǎng)度等,注意指定這里的動(dòng)態(tài)是計(jì)算的一個(gè)值)。就這樣;新式的瀏覽器指定并把一個(gè)行解析成圖片,覆蓋第一行的豐富內(nèi)容。
后面的課程我們會(huì)討論更多關(guān)于瀏覽器的連接問(wèn)題。
恭喜你完成本模塊,下面的文章你用你的新知識(shí)來(lái)完成覆蓋樣式的案例,在這個(gè)過(guò)程中測(cè)試一些 CSS 樣式。
理解JavaScript運(yùn)行原理,我們需要理解以下兩方面內(nèi)容。
JavaScript引擎是一個(gè)計(jì)算機(jī)程序,它的主要作用是JavaScript運(yùn)行時(shí)將源碼編譯為機(jī)器碼。
每個(gè)主流Web瀏覽器都有自己的JavaScript引擎,它通常由web瀏覽器供應(yīng)商開(kāi)發(fā)。
主流web瀏覽器
以前的JavaScript引擎主要在web瀏覽器使用,不過(guò)隨著nodejs的出現(xiàn)就打破了這種局限。
V8包含了解析器(parser),解釋器(Ignition),優(yōu)化編譯器(TurboFan )。
解析器(parser):用于生成抽象語(yǔ)法樹(shù)。
JavaScript代碼的句法結(jié)構(gòu)的樹(shù)形表示形式
解釋器(Ignition):將源碼轉(zhuǎn)換為字節(jié)碼。
解釋器
優(yōu)化編譯器(TurboFan ):進(jìn)行一些優(yōu)化編譯優(yōu)化處理,比如內(nèi)聯(lián)緩存。
下面是V8引擎的大體工作流程。
源碼轉(zhuǎn)化為機(jī)器碼流程
瀏覽器運(yùn)行環(huán)境中,瀏覽器提供了Web API,如:HTTP請(qǐng)求,計(jì)時(shí)器,事件等。
服務(wù)器運(yùn)行環(huán)境中,nodejs提供了API。
下面是JavaScript在瀏覽器中運(yùn)行時(shí)的架構(gòu),它包含一個(gè)內(nèi)存堆、一個(gè)內(nèi)存棧、一個(gè)事件循環(huán)、一個(gè)回調(diào)隊(duì)列。
JavaScript運(yùn)行時(shí)架構(gòu)
下面代碼展示了JavaScript執(zhí)行的調(diào)用棧變化。
JavaScript調(diào)用棧
function add(x, y) {
return x + y;
}
function print(x, y) {
console.log('x+y=',add(x, y))
}
print(1, 3)
JavaScript先執(zhí)行了print函數(shù),然后調(diào)用Web API setTimeout(),Web API存儲(chǔ)了setTimeout() 的回調(diào)函數(shù),3秒后將回調(diào)函數(shù)添加到回調(diào)隊(duì)列,事件循環(huán)發(fā)現(xiàn)調(diào)用棧為空,于是將隊(duì)列里的回調(diào)函數(shù)移至調(diào)用棧執(zhí)行。
異步任務(wù)
function add(x, y) {
return x + y;
}
function print(x, y) {
setTimeout(function (){
console.log('x+y=',add(x, y))
}, 3000)
}
print(1, 3)
JavaScript運(yùn)行主要依靠JavaScript引擎和運(yùn)行環(huán)境,引擎將js源碼翻譯成計(jì)算機(jī)所理解的機(jī)器碼,運(yùn)行環(huán)境提供了一些與計(jì)算機(jī)底層通訊的API和運(yùn)行實(shí)現(xiàn)。
者:Lydia Hallie
譯者:前端小智
來(lái)源:dev
JavaScript 很酷,但是 JS 引擎是如何才能理解我們編寫(xiě)的代碼呢?作為 JS 開(kāi)發(fā)人員,我們通常不需要自己處理編譯器。然而,了解 JS 引擎的基礎(chǔ)知識(shí)并了解它如何處理JS代碼,并將其轉(zhuǎn)換成機(jī)器能夠理解的東西,絕對(duì)是個(gè)有益無(wú)害的事情。
注意:本文主要基于 Node.js 和基于 Chrome 的瀏覽器使用的 V8 引擎。
HTML解析器遇到帶有源代碼的script標(biāo)簽。來(lái)自此源的代碼從網(wǎng)絡(luò),緩存或已安裝的服務(wù)工作程序中加載。響應(yīng)是將請(qǐng)求的腳本作為字節(jié)流,由字節(jié)流解碼器負(fù)責(zé)。字節(jié)流解碼器在下載字節(jié)流時(shí)對(duì)其進(jìn)行解碼。
字節(jié)流解碼器從已解碼的字節(jié)流中創(chuàng)建令牌。例如,0066解碼為f, 0075到u,006e到n, 0063到c, 0074到t, 0069到i, 006f到o, 006e到n,后面跟一個(gè)空格。就像JS中的function,這是 JS 中的一個(gè)保留關(guān)鍵字,它會(huì)創(chuàng)建一個(gè)標(biāo)記,并將其發(fā)送給解析器。對(duì)于字節(jié)流的其余部分也是如此。
該引擎使用兩個(gè)解析器:預(yù)解析器(pre-parser)和解析器(parser)。預(yù)解析器只提前檢查標(biāo)記,以查看是否有語(yǔ)法錯(cuò)誤。這可以減少發(fā)現(xiàn)代碼中的錯(cuò)誤所需的時(shí)間,否則解析器稍后就會(huì)發(fā)現(xiàn)這些錯(cuò)誤。
如果沒(méi)有錯(cuò)誤,解析器將根據(jù)從字節(jié)流解碼器接收到的標(biāo)記創(chuàng)建節(jié)點(diǎn)。使用這些節(jié)點(diǎn),它創(chuàng)建了一個(gè)抽象語(yǔ)法樹(shù),即AST。
接下來(lái),輪到解釋器(interpreter)了。遍歷AST并根據(jù)AST包含的信息生成字節(jié)碼的解釋器。一旦字節(jié)碼完全生成,AST就會(huì)被刪除,從而清除內(nèi)存空間。最后,生成的機(jī)器碼就可以在電腦上運(yùn)行了。
雖然字節(jié)碼很快,但它可以更快。當(dāng)這個(gè)字節(jié)碼運(yùn)行時(shí),將生成信息。它可以檢測(cè)某些行為是否經(jīng)常發(fā)生,以及所使用數(shù)據(jù)的類(lèi)型。也許已經(jīng)調(diào)用一個(gè)函數(shù)幾十次了:現(xiàn)在是時(shí)候優(yōu)化它了,這樣它會(huì)運(yùn)行得更快!
字節(jié)碼與生成的類(lèi)型反饋一起發(fā)送到優(yōu)化編譯器(ptimizing compiler)。優(yōu)化的編譯器接收字節(jié)碼和類(lèi)型反饋,并根據(jù)這些信息生成高度優(yōu)化的機(jī)器碼。
JS 是一種動(dòng)態(tài)類(lèi)型語(yǔ)言,這意味著數(shù)據(jù)類(lèi)型可以不斷變化。如果 JS引擎每次都要檢查某個(gè)值的數(shù)據(jù)類(lèi)型,那么速度會(huì)非常慢。
相反,JS 引擎使用一種稱(chēng)為內(nèi)聯(lián)緩存(inline caching)的技術(shù)。它將代碼緩存在內(nèi)存中,希望將來(lái)它會(huì)以相同的行為返回相同的值.假設(shè)某個(gè)函數(shù)被調(diào)用100次,并且到目前為止總是返回相同的值。它將假設(shè)在第101次調(diào)用它時(shí)也會(huì)返回這個(gè)值。
假設(shè)我們有以下函數(shù)sum,(到目前為止)每次都使用數(shù)值作為參數(shù)來(lái)調(diào)用它:
ffunction sum(a, b){
return a + b
}
sum(1, 2
執(zhí)行結(jié)果為 3。下次調(diào)用它時(shí),它將假定我們?cè)俅问褂脙蓚€(gè)相同數(shù)字對(duì)其進(jìn)行調(diào)用。
如果假投,那么就不需要?jiǎng)討B(tài)查找,只需要使用存儲(chǔ)在特定內(nèi)存槽中的結(jié)果,該槽已經(jīng)有一個(gè)引用。否則,如果假設(shè)不正確,它將反優(yōu)化代碼并恢復(fù)到原始字節(jié)碼,而不是優(yōu)化后的機(jī)器碼。
例如,下一次調(diào)用它時(shí),我們傳遞的是字符串而不是數(shù)字。因?yàn)?JS 是動(dòng)態(tài)類(lèi)型的,所以這樣做不會(huì)有任何錯(cuò)誤。
function sum(a, b){
return a + b
}
sum('1', 2)
這意味著數(shù)字2將被強(qiáng)制轉(zhuǎn)換成字符串,而函數(shù)將返回字符串'12'。它返回執(zhí)行解釋的字節(jié)碼并更新類(lèi)型反饋。
我希望這篇文章對(duì)你有用!當(dāng)然,在這篇文章中還沒(méi)有涉及到引擎的更多部分(JS堆,調(diào)用堆棧,等等),后續(xù)會(huì)繼續(xù)分享。如果你對(duì) JS 的內(nèi)部機(jī)制感興趣,強(qiáng)烈建議自己可以做一些研究,V8 是開(kāi)源的,并且有一些很棒的文檔說(shuō)明它是如何工作的。
https://dev.to/lydiahallie/javascript-visualized-the-javascript-engine-4cdf
*請(qǐng)認(rèn)真填寫(xiě)需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。