我不知道的Script标签
前言 :对于script标签,经常面试的jym应该都非常熟悉,在各类的面试题中都会出现如下一些问题:
-
最经典的script标签的async和defer属性的区别
1. 对于defer,html5的规范要求脚本要按照他们出现的顺序执行中,但实际上,脚步不一定会按顺序执行或者在DOMContentLoaded事件之前执行。最好只有一个defer
-
src属性和href属性的区别
但是以上都不是要分享的内容,今天就以下面的例子来展开,这些都是最近再看红宝书时留意到的,以前没有怎么去注意,23年的前端只会框架。非常离谱
开胃小菜1:
```js
<script src="https://juejin.cn/">
function sayScript() {
console.log('123')
}
sayScript()
</script>
```
能输出字符串123吗?奥夫扣死闹特。
当script同时存在行内代码和外部文件引用时,则只会下载外部文件而去忽略行内代码
开胃小菜2:
<script>
function sayScript() {
console.log('</script>')
}
sayScript()
</script>
能输出</script>吗?奥夫扣死闹特。
在编译阶段就有报错了
还没执行在编辑器中已经出现报错,可以看到提示我们的
</script>标签没有对应开始标签。对于script标签是比较特殊的。浏览器在解析行内脚本的过程中,看到字符串</script>,会将其当成结束的</script>标签。目前测试下来只有这个标签作为字符串才会出现。解决就是使用转义字符\,将</script>转义成<\/script>
正菜上了:
先引用红宝书对于script标签的一段描述:script请求不受浏览器同源策略限制,但返回并被执行的JavaScript则受限制。当然,这个请求仍然受父页面HTTP/HTTPS协议的限制。
-
对于
返回并被执行的JavaScript则受限制,这边分为两点:- 数据请求交换受限(侧重服务器请求):如果script引入的脚本中包含如ajax请求之类的,那么这类请求就会受到同源策略的限制。
- 执行上下文受限 (侧重权限):如果页面A引入脚本X,对于同源的脚本,那么脚本可以自由使用页面中的dom、变量、函数等资源,但是对于跨域的脚本,即使他也可以在A的执行上下文中运行,但是对于声明在其它脚本块中定义的函数和变量以及localStorage和Cookie是不能够读取修改的的。只有通过window.postMessage()、或者将变量方法绑定到全局上。
-
对于
受父页面HTTP/HTTPS协议的限制,这个是根据主页面的启动方式控制的,也就是页面地址开头的协议,如果父页面协议是http,那么对于src,你可以使用还是https链接一定程度的提升数据传输的安全性,像我们经常使用的cdn<script src="https://cdn.staticfile.net/vue/2.2.2/vue.min.js"></script>,当然也可以使用http,例如<script src="http://43.139.11.133:888"></script>都是可以正常访问的。
如果父页面的启动协议是https,那么我们一一验证src允许使用的协议,为了方便,我就直接在jj(juejin.cn/)上使用动态添加script标签的方式。
src="https://":
const dom = document.createElement('script')
dom.src = 'https://cdn.staticfile.net/vue/2.2.2/vue.min.js'
dom.addEventListener('load', (x) => {console.log(1,x)})
document.head.appendChild(dom)
可以看出script是完成加载了
-
src="http://":重复上述步骤。const dom = document.createElement('script') dom.src = 'https://43.139.11.133:888' dom.addEventListener('load', (x) => {console.log(1,x)}) document.head.appendChild(dom)
可以看到报错信息: Mixed Content: The page at 'https://juejin.cn/' was loaded over HTTPS, but requested an insecure script 'http://43.139.11.133:888/'. This request has been blocked; the content must be served over HTTPS.提示jj是通过https加载的,但是请求了不安全的脚本,必须使用https协议。
总结:如果页面是通过https协议启动的,那么src只能使用https协议,如果页面是http协议启动那么https/http协议都可以使用。
PS:
最后,最近在学习node+express,以及选择性看下红宝书和css高级以及leetcode,会不定期输出随笔,方便后期查阅,总结一下成果和一些以往没注意到信息。可能内容很简单。