地址栏输入一段url会发生什么事情?
1、题目分析:这套题目比较开放,可以围绕以下几个点来回答:
- DNS域名解析过程
- js时间线
- 浏览器解析javaScript三部曲
2、精简版答案:
首先,通过域名解析系统解析浏览器地址(本地文件缓存,浏览器缓存,路由缓存,ISP DNS缓存,递归搜索…)找到对应的ip地址,发送请求;
其次,服务器收到请求会给浏览器响应一段数据,浏览器收到数据后,开始解析文档(js时间线);
然后,当文档解析完成后执行js代码,这个过程就是js执行三部曲(语法检测,预编译,解释执行代码);
最后,所有过程执行完毕!
3、衍生出来的一些问题解答:
3.1、js时间线(JavaScript加载的过程、时间线的步骤)
- 创建Document对象,开始解析web页面,解析HTML元素和他们的文本内容后添加Element对象和Text节点到文档中。这个阶段Document。readyState
= “loading”。 - 遇到link外部css,创建线程加载,并继续解析文档。
- 遇到script外部js,并且没有设置async , defer ,浏览器加载,并阻塞,等待js加载完成并执行该脚本,然后继续解析文档
- 遇到script外部js,并且设置有async,defer 浏览器创建线程加载,并继续解析文档,对于async属性的脚本,脚本加载完成后立即执行(异步禁止使用docuemnt.write())。
- 遇到img标签等,先正常解析dom结构,然后浏览器异步加载src,并继续解析文档
- 当文档解析完成,document.readyState = “interactive”;
- 文档解析完成后,所有设置有defer的脚本会按照顺序执行。
- 当文档解析完成之后,document对象触发DOMContentLoaded事件,这也标志着程序执行从同步脚本执行阶段,转化为事件驱动阶段
- 当所有async的脚本加载完成并执行后,img等加载完成后,document.readyState = “complete” window对象触发load事件
- 从此,页面以异步响应方式处理用户输入,网络事件等。
精简版:创建Document对象,浏览器开始解析html页面document.readyState = “loading”。 2.当遇到外部资源(外部的js文件,外部的css文件,外部的图片,a标签,iframe标签)的时候,除了script中的src(没有设置defer,async)为同步,其余都为异步(主线程调用子线程完成)有且只有这一个script标签中的src为同步,等待js加载完成并执行该脚本,继续解析文档至完成,document.readyState = “interactive” ,所有异步线程会按照顺序依次执行,同时document对象触发DOMContentLoaded事件(jquery中ready方法的封装),等待所有异步线程加载完毕,document.readyState=‘complete’.
3.2、JS运行时三部曲
JS运行三部曲
1.语法检测
先全部检测一遍 看有没有语法错误.
2.预编译(执行前一刻)
函数声明整体提升
变量 声明提升
3.解释执行
(解释一行执行一行)
预编译执行四部曲
函数中
1.创建AO对象 (Activation Object (执行期上下文))
2. 找形参和变量声明,将变量和形参名作为AO属性名,值为undefined
3.将实参值和形参统一
4.在函数体里面找函数声明,值赋予函数体
全局中
1. 生成一个叫GO 对象 Global Object
(window就是全局)
例子:
<script>
/*首先执行前会进行全局预编译:
先把全局的变量声明找出来值为undefined 和函数声明 值赋予函数体,提升到最上端
GO{a:undefined;
demo:function demo(e){.....}
} 然后开始执行*/
a = 100; //1.执行到这里 GO{a:100; 把100 赋值给a 然后下一行
function demo(e){ //2.执行到这里 因为demo:function demo(e){.....} 提升 所以忽略 然后下一步
function e(){} //5.提升 忽略
arguments[0] = 2; //6.实参值改变 形参也改变 AO{ e:2;
console.log(e); //7. 输出 2
if (a){ //8. a此刻为 AO{ a:undefined; 所有if整段代码不执行
var b = 123;
}
var c; //9.提升 忽略
a = 10; // 10. AO{ a:10;
var a; //11.提升 忽略
console.log(b); //12.因为AO{ b;undefined; 所以 输出 undefined
f = 123; //13.因为 AO中没有f ,所以把f放入GO中GO{f:undefined; 把123赋值给它GO{f:123;
console.log(c); //14.因为AO{ c;undefined; 所以输出 undefined
console.log(a); //15. 看10步 AO{ a:10; 输出 10 执行完毕
}
var a; //3. 提升 忽略 下一步
//4.函数执行前进行函数预编译
/*4.1找形参和变量声明,将变量和形参名作为AO属性名,值为undefine
AO{ e:undefined;
c:undefined;
a:undefined;
}
4.2将实参值和形参统一
AO{ e:1;
c:undefined;
a:undefined;
}
4.3在函数体里面找函数声明,值赋予函数体
AO{ e: function e(){};
b;undefined;
c:undefined;
a:undefined;
}
*/
demo(1);
console.log(a); //100 //16. 看1. GO{a:100; 输出 100
console.log(f); //123 //17.看 13. GO{f:123; 输出 123
</script>