熟悉的< script >標籤

zhangfaliang發表於2019-01-23

作為前端開發的小夥伴,一看到< script >標籤,是不是特別熟悉,因為前端開發的小夥們每天基本都會使用該標籤,但是仔細想想真的對< script >標籤瞭解嗎,它的的作用是什麼?它的位置應該放在哪?為啥這樣放?它有幾個屬性?每個屬性是幹什麼的?當然有些小夥伴已經知道個大概了,那麼我們們就帶著這幾個問題,來真正的瞭解一下熟悉的< script>標籤

1 < script > < /script >標籤的產生

我們經常使用的< script > < /script >標籤,大家都知道它是放在web核心語言HTML的標籤,當初在開發JavaScript的時候,遠景公司,為了解決一個重要的問題,就是如何做到JavaScript既能與HTML頁面共存,又不影響頁面的顯示效果,經過嘗試、糾錯和爭論,最終決定就是給web增加統一的指令碼支援。這些早期的很多做法也被保留了下來,並正式納入HTML規範當中。這就是< script>的產生 ,可以檢視《有關javascript的發展史》

2 < script > < /script >標籤的屬性

前端開發的小夥伴看這個熟悉的< script > < /script >標籤,能回答出來有幾個屬性嗎?可能聰明的小夥伴已經知道了,6個!沒錯就是6個。

  • 1 type
  • 2 src
  • 3 defer
  • 4 async
  • 5 language
  • 6 charset

大家對這個6個屬性,比較熟悉的可能依次是 type、src、async、defer,剩下的哪兩個可能就不太熟悉了,接下我們們就一起看一下這些屬性的用途,這6個屬性都是可選的。

2.1 type屬性。

前端小夥伴一下到type屬性就會想到type='text/javascript',其實type屬性預設值就是text/javascript,type是代替已經廢棄的language屬性,表示編寫程式碼使用的指令碼語言的內容型別(也可以成為MIME型別),雖然text/javascript和text/ecmascript都已經不被推薦使用了。但是大家一致用text/javascript,它還有其他屬性值如
application/x-javascriot(但是這個屬性會導致指令碼會被忽略)
application/javascript|applicationecmascript(考慮到瀏覽器相容,當然現在的瀏覽器不用考慮這些)

2.2 src屬性

前端小夥伴對src的屬性的熟悉度不會低於type,因為現在js的開發一把都是放在js檔案中,這樣有利於集中開發和html文件清潔。
一般的情況下大家都會在src的屬性值中填寫一個相對路徑或者與當前域名一直的js路徑,因為這樣可以保證js檔案的來源和安全
某些情況下src的屬性值也可能是一個非同域名的地址,但是這個地址最好是自己知道並可以維護的地址,這樣可能會出現跨域指令碼攻擊,得到以下敏感資訊,來操作你的使用者資訊和賬戶金額等
大家看一下下面,會不會在控制檯輸出index.js字串

<html>
<head></head>
<body></body>
< script src='/index.js' > 
    console.log('index.js')
< /script >
</html>

複製程式碼

答案是不能,因為當使用了src外部資源的時候,瀏覽器就不會再解析執行< script>內部的程式碼塊了。

2.3 defer屬性

該屬性是html4.01為< script>標籤放在< head>中定義的
,在執行的時候不會影響到頁面構造。

//index.js
   document.getElementById('root')
// index.html
<html>
<head>
< script src='/index.js' defer='defer' > < /script >
</head>
<body>
    <div id ='root'></root>
</body>

</html>
複製程式碼

目的是告訴瀏覽器,可以立即下載js,但是延遲執行程式碼。

//index1.js
   document.getElementById('root')
// index.html
//index2.js
   document.getElementById('root')
// index.html
<html>
<head>
< script src='/index1.js' defer='defer' > < /script >
< script src='/index2.js' defer='defer' > < /script >
</head>
<body>
    <div id ='root'></root>
</body>

</html>
複製程式碼

但是在HTML5的規範中要求指令碼按照它們出現的先後順序執行,因此第一個延遲執行的指令碼會先於第二個延遲執行,而這兩個指令碼會先於DOMContentLoaded事件執行。
實際上在不支援html5規範的瀏覽器上,延遲不一定會按照順序執行,也不一定會先於DOMContentLoaded事件執行,因此一個最好包含一個延遲指令碼

2.4 asycn 非同步指令碼

HTML5為< script>元素定義了async屬性。這個屬性與我們們看的上面的defer類似,async只適合外部指令碼檔案,告訴瀏覽器立即下載檔案,但於defer不同的async並不保證按照它們的出現先後順序執行

//index1.js
   document.getElementById('root')
// index.html
//index2.js
   document.getElementById('root')
// index.html

<!DOCTYPE html>
<html>
<head>
< script src='/index1.js' async > < /script >
< script src='/index2.js' async > < /script >
</head>
<body>
    <div id ='root'></root>
</body>

</html>
複製程式碼

上面程式碼不確定 index1.js會先執行與index2.js,所以一定要保證index2.js不依賴與index1.js

2.5 language 屬性

該屬性已被廢棄,我們們大家只做瞭解,原來用於表示編寫怠慢使用的指令碼語言,(JavaScript、JavaScript1.2或者VBScript),但是大多數瀏覽器都會忽略這個屬性,因此沒有必要在使用了。

2.6 charset 屬性

可選。表示通過 src 屬性指定的程式碼的字符集。由於大多數瀏覽器會忽略它的值, 因此這個屬性很少有人用。

3 < script > < /script >的使用

3.1 嵌入使用,看程式碼

<!DOCTYPE html>
<html>
<head>


</head>
<body>
    <div id ='root'></root>
</body>
< script  > 
    function sayHi(){
         console.log('Hi')
    }
  
< /script >
</html>
複製程式碼

包含著< script>內部的程式碼將被從上到下依次解釋,直譯器解釋一個函式的定義,然後將該定義儲存到自己的環境中。在直譯器對< script>元素內部的所有程式碼求值完畢以前,頁面中的其餘內容都不會被瀏覽器載入或者顯示。
在使用< script> 嵌入JavaScript程式碼時,不要在程式碼證任何地方出現“”字串。

<!DOCTYPE html>
<html>
<head>


</head>
<body>
    <div id ='root'></root>
</body>
< script  > 
    function sayHi(){
         console.log("< /script >"")
    }
  
< /script >
</html>
複製程式碼

在瀏覽器中載入時會出現一個錯誤。

3.2 外部引入

<!DOCTYPE html>
<html>
<head>
< script src='/index1.js' async > < /script >
</head>
<body>
    <div id ='root'></root>
</body>

</html>
複製程式碼

這種引入方式和嵌入的載入順序一樣,但是多了一步下載流程。但是他的好處是非常大的,

  • 1可以統一集中的管理開發js
  • 2相比嵌入式對html的整潔性有很大的太高
  • 3 有利於分離開發

雖然有好處很大,但是也會出現以下載入位置或者載入順序的問題。
從上面的得到,在瀏覽器載入的時候,瀏覽器只會一心一意的載入解析js程式碼,其他的工作都會先放下,那麼問題來了。

<!DOCTYPE html>
<html>
<head>
< script src='/index1.js'> < /script >
</head>
<body>
    <div id ='root'></root>
</body>

</html>
複製程式碼

如果index1.js程式碼解析的比較慢的話,頁面就會出現一個空白頁面。
如果index1.js程式碼解析的很快的話,由於index1.js中操作了某個dom其實,是無效的。
根據我們們瞭解的< script>標籤的 async 和 defer的屬性我們們可以解決,空白頁面的問題。
但是async 和 defer的屬性都有自己的侷限性

  • 1 async 能夠保證不立即執行js程式碼,但是無法保證兩個外鏈程式碼的執行順序
  • 2 defer 雖然規定了,能夠保證不立即執行js程式碼,保證外鏈程式碼的執行順序,但是一般瀏覽器不是這麼做的

那麼最好的解決方案是,需要把< script >標籤放在底部

這就是我們常用的< script>大家是不是有跟進一步的瞭解這這個標籤,歡迎大家補充不足的地方,歡迎留言點贊

相關文章