作者水平有限,如果文中出现错误,欢迎读者在评论中指出,谢谢!
本文将无限期更新...
1、new一个对象都发生了什么
new的过程
- 创建一个空的对象,并且将构造函数中的this指向刚创建的空对象;
- 将新创建的对象进行
原型连接; - 逐行执行构造函数中的代码,属性和方法被添加到this引用的对象中;
- 如果构造函数中返回了其他对象则返回这个对象,否则返回this;
function _new(){
//新创建的对象
let target = {}
let [constructor,...args] = [...arguments]
//执行原型连接
target.__proto__ = constructor.prototype
//执行构造函数中的代码
let result = constructor.apply(target,args)
if( result && ( typeof(result) == 'object' || typeof(result) == 'function' )){
//如果构造函数执行的结构返回一个对象,则返回这个对象
return result
}
//如果构造函数返回的不是一个对象,则返回新创建的对象
return target
}
2、闭包
- 在
JavaScript高级程序设计中对闭包的解释为:
闭包是指有权访问另一个函数作用域中的变量的函数。
2.在JavaScript权威指南中对闭包的解释为:
从技术的角度讲,所有的JavaScript函数都是闭包:它们都是对象,它们都关联到作用域链。
3.在你不知道的JavaScript中对闭包的解释为:
当函数可以记住并访问所在的词法作用域时,就产生了闭包,即使函数是在当前词法作用域之外执行。
总之一个函数嵌套并return另一个函数,内层函数引用了外层函数中的的变量,内部函数又被外层变量所引用,这就形成了闭包。
手动实现一个闭包
function foo(){
let str = '不爱我就拉倒~'
//还是上面那句话
//一个函数嵌套并return另一个函数
return function(){
//内层函数引用了外层函数中的的变量
console.log(str)
}
}
//内部函数又被外层变量所引用
let func = foo()
func() //不爱我就拉倒~
使用闭包实现单例模式
咱先看看不使用闭包的情况下如何实现单例模式:
var Singleton = function(name){
this.name = name
this.instance = null
}
Singleton.prototype.getName = function(){
return this.name
}
// 获取实例对象
function getInstance(name) {
if( !this.instance ) {
this.instance = new Singleton(name);
}
return this.instance
}
// 测试单例模式的实例
var one = getInstance("aa")
var two = getInstance("bb")
console.log( one === two ) //true
/*
* 由于单例模式只实例化一次,因此第一次调用,返回的是a实例对象,当我们继续调用的时候,b的实例就是a 的实例,因此下面都是打印的是aa
* console.log(one.getName());// aa
* console.log(two.getName());// aa
*/
接下来使用闭包来实现一个单例模式:
var Singleton = function(name){
this.name = name
}
Singleton.prototype.getName = function(){
return this.name
}
// 获取实例对象
var getInstance = (function() {
var instance = null
//闭包
return function(name) {
if(!instance) {
instance = new Singleton(name)
}
return instance
}
})()
// 测试单体模式的实例
var one = getInstance("aa")
var two = getInstance("bb")
console.log( one === two ) //true
3、从输入url地址栏,发生了什么?
- 浏览器向 DNS 服务器请求解析该 URL 中的域名所对应的 IP 地址;
- 建立TCP连接(三次握手);
- 浏览器发出读取文件(URL 中域名后面部分对应的文件)的HTTP 请求,该请求报文作为 TCP 三次握手的第三个报文的数据发送给服务器;
- 服务器对浏览器请求作出响应,并把对应的 html 文本发送给浏览器;
- 浏览器将该 html 文本并显示内容;
- 释放 TCP连接(四次挥手);
上面这个问题是一个面试官非常喜欢问的问题,接下来咱把这6个步骤分解,挑几个重要来进行逐步细谈...
1、DNS解析
DNS解析:将域名解析为ip地址 ,由上往下匹配,只要命中便停止。
- 走缓存
- 浏览器DNS缓存
- 本机DNS缓存
- 路由器DNS缓存
- 网络运营商服务器DNS缓存 (80%的DNS解析在这完成的)
- 递归查询
2、TCP的三次握手
SYN (同步序列编号)ACK(确认字符)
第一次握手:Client将标志位SYN置为1,随机产生一个值seq=J,并将该数据包发送给Server,Client进入SYN_SENT状态,等 待Server确认。
第二次握手:Server收到数据包后由标志位SYN=1知道Client请求建立连接,Server将标志位SYN和ACK都置为1,ack=J+1,随机产生一个值seq=K,并将该数据包发送给Client以确认连接请求,Server进入SYN_RCVD状态。
第三次握手:Client收到确认后,检查ack是否为J+1,ACK是否为1,如果正确则将标志位ACK置为1,ack=K+1,并将该数据包发送给Server,Server检查ack是否为K+1,ACK是否为1,如果正确则连接建立成功,Client和Server进入ESTABLISHED状态,完成三次握手,随后Client与Server之间可以开始传输数据了。
3、浏览器发送请求
略过...
4、服务器返回响应,浏览器接受到响应数据
略过...
5、浏览器解析数据,绘制渲染页面的过程
这是重点...
- 先预解析(将需要发送请求的标签的请求发出去);
- 从上到下解析html文件;
- 遇到HTML标签,调用html解析器将其解析DOM树;
- 遇到css标记,调用css解析器将其解析CSSOM树;
- link 阻塞 - 为了解决闪屏,所有解决闪屏的样式;
- style 非阻塞,与闪屏的样式不相关的;
- 将DOM树和CSSOM树结合在一起,形成render树;
- layout布局 render渲染;
- 遇到script标签,阻塞,调用js解析器解析js代码,可能会修改DOM树,也可能会修改CSSOM树;
- 将DOM树和CSSOM树结合在一起,形成render树;
- layout布局 render渲染(重排重绘);
- script标签的属性 asnyc defer;
6、TCP的四次挥手,断开连接
略过...