前端进阶必备知识点(一)

作者水平有限,如果文中出现错误,欢迎读者在评论中指出,谢谢!
本文将无限期更新...

1、new一个对象都发生了什么

new的过程

  1. 创建一个空的对象,并且将构造函数中的this指向刚创建的空对象;
  2. 将新创建的对象进行原型连接;
  3. 逐行执行构造函数中的代码,属性和方法被添加到this引用的对象中;
  4. 如果构造函数中返回了其他对象则返回这个对象,否则返回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、闭包

  1. 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地址栏,发生了什么?

  1. 浏览器向 DNS 服务器请求解析该 URL 中的域名所对应的 IP 地址;
  2. 建立TCP连接(三次握手);
  3. 浏览器发出读取文件(URL 中域名后面部分对应的文件)的HTTP 请求,该请求报文作为 TCP 三次握手的第三个报文的数据发送给服务器;
  4. 服务器对浏览器请求作出响应,并把对应的 html 文本发送给浏览器;
  5. 浏览器将该 html 文本并显示内容;
  6. 释放 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、浏览器解析数据,绘制渲染页面的过程
这是重点...

  1. 先预解析(将需要发送请求的标签的请求发出去);
  2. 从上到下解析html文件;
  3. 遇到HTML标签,调用html解析器将其解析DOM树;
  4. 遇到css标记,调用css解析器将其解析CSSOM树;
  5. link 阻塞 - 为了解决闪屏,所有解决闪屏的样式;
  6. style 非阻塞,与闪屏的样式不相关的;
  7. 将DOM树和CSSOM树结合在一起,形成render树;
  8. layout布局 render渲染;
  9. 遇到script标签,阻塞,调用js解析器解析js代码,可能会修改DOM树,也可能会修改CSSOM树;
  10. 将DOM树和CSSOM树结合在一起,形成render树;
  11. layout布局 render渲染(重排重绘);
  12. script标签的属性 asnyc defer;

6、TCP的四次挥手,断开连接
略过...

未完待续...

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。