1. 原型与原型链123456function Person() { }const person = new Person()person.name = 'cuifanfan'console.log(person.name) // cuifanfan
在这个例子中,Person 就是一个构造函数,我们使用 new 创建了一个实例对象 person。
1.1 prototype每个函数都有一个prototype属性,就是我们经常在各种例子中看到的那个prototype,它指向了一个对象,这个对象正是调用该构造函数而创建的实例的原型。
什么是原型呢?你可以这样理解:每一个JavaScript对象(null除外)在创建的时候就会与之关联另一个对象,这个对象就是我们所说的原型,每一个对象都会从原型”继承”属性。
12345678910function Person() {}// prototype是函数才会有的属性Person.prototype.name = 'cuifanfan'const pers ...
1. 浏览器怎么实现setTimeout渲染进程所有运行在主线程上的任务都要首先添加到消息队列,然后事件循环系统按照顺序执行消息队列中的任务。那么有哪些典型的事件呢?
当接收到HTML文档数据,渲染引擎就会将“解析DOM“事件添加到消息队列中
当用户改变了Web页面的窗口大小,渲染引擎就会将“重新布局”事件添加到消息队列中
当触发了JavaScript引擎垃圾回收机制,渲染引擎就会将”垃圾回收“任务添加到消息队列中
当执行一段异步JavaScript代码,也会把需要执行任务添加到消息队列中回调函数是在指定的时间间隔内被调用,但是消息队列中的任务是按照顺序被执行的,所以定时器中的任务不能直接添加到消息队列中。那么怎么在消息循环系统的基础上添加定时器的功能呢?
其实在Chrome中,除了正常使用的消息队列外,还有一个HashMap,其中维护了需要延迟执行的任务,包括定时器和Chromium内部需要延迟执行的任务。当通过JavaScript创建一个定时器的时候,渲染进程会将该定时器中的回调任务添加到该HashMap中。
通过JavaScript调用setTimeout设置回调函数的时候, ...
1. HTTP介绍1.1 HTTP概括HTTP全称是超文本传输协议。它定义了客户端和服务器之间交换报文的格式和方式,默认使用 80 端口。它使用 TCP 作为传输层协议,保证了数据传输的可靠性。
HTTP 是一个无状态的协议,HTTP 服务器不会保存关于客户的任何信息。
HTTP 有两种连接模式,一种是持续连接,一种非持续连接。非持续连接指的是服务器必须为每一个请求的对象建立和维护 一个全新的连接。持续连接下,TCP 连接默认不关闭,可以被多个请求复用。采用持续连接的好处是可以避免每次建立 TCP 连接三次握手时所花费的时间。
1.2 HTTP报文HTTP 请求报文的格式如下:
第一行叫做请求行,后面的行叫做首部行,首部行后还可以跟一个实体主体。请求首部之后有一个空行,这个空行不能省略,它用来划分首部与实体。
请求行包含三个字段:方法字段、URL 字段和 HTTP 版本字段。
方法字段可以取几种不同的值,一般有 GET、POST、HEAD、PUT 和 DELETE。
一般GET 方法只被用于向服务器获取数据。 POST 方法用于将实体提交到指定的资源,通常会造成服务器资源的修改。HE ...
每个渲染进程都有一个主线程,主线程非常繁忙,既要处理DOM、计算样式,还要处理布局,同时还要注意JavaScript任务和各种输入事件。要让这么多不同类型的任务在主线程中有条不紊地执行,需要一个系统来统筹调度。这也是消息队列和事件循环系统出现的原因。
让我们一起从最简单的场景开始分析,一步一步了解浏览器页面主线程是如何运作的。
1. 使用单线程处理安排好的任务假如有一系列下列这些任务:
1234任务1:1+2任务2:21 / 7任务3:7*8任务4:打印前3个任务的结果
要在一个线程中执行这些任务,我们通常会这样编写代码:
123456function MainThread() { let num1 = 1+2 let num2 = 21/7 let num3 = 7*8 console.log(num1,num2,num3)}
它的执行过程参考下图:
2. 在线程执行过程中执行新任务但并不是所有的任务都是在执行之前统一安排好的,大部分情况下,新的任务是在线程运行过程中产生的。比如在线程执行过程中,又接收到了一个新的任务要求计算“21+ ...
页面是浏览器的核心,浏览器中的所有功能点都是服务于页面的,而 Chrome 开发者工具又是工程师调试页面的核心工具,熟练使用它能让你更加深入地了解浏览器内部工作原理。
本篇文章主要聚焦于焦页面的源头和网络数据的接收,这些发送和接收的数据都能体现在开发者工具的网络面板上。
Chrome 开发者工具有很多重要的面板,比如与性能相关的有网络面板、Performance 面板、内存面板等,与调试页面相关的有 Elements 面板、Sources 面板、Console 面板等。你可以在浏览器窗口的右上方选择 Chrome 菜单,然后选择“更多工具–> 开发者工具”来打开 Chrome 开发者工具。
从图中可以看出,它一共包含了 10 个功能面板,包括了 Elements、Console、Sources、NetWork、Performance、Memory、Application、Security、Audits 和 Layers。关于这 10 个面板的大致功能,我做了一个表格,感兴趣的话,你可以详细看下:
简单来说,Chrome 开发者工具为我们提供了通过界面访问或者编辑 DOM 和 ...
Promise虽然使得异步编程更加线性化,但是代码里面包含了大量的 then 函数,使得代码依然不是太容易阅读。基于这个原因,ES7 引入了 async/await,这是 JavaScript 异步编程的一个重大改进,提供了在不阻塞主线程的情况下使用同步代码实现异步访问资源的能力,并且使得代码逻辑更清晰。
123456789fetch('https://www.baidu.org') .then((response) => { console.log(response) return fetch('https://www.baidu.org/test') }).then((response) => { console.log(response) }).catch((error) => { console.log(error) })
改为await-async:
123456789101112async function foo ...
1. 什么是promisepromise是JavaScript中异步编程的一种新解决方案。
从语法上来说,promise是一个构造函数。
从功能上来说,promise对象封装一个异步操作并可以获取它成功或者失败的结果值。
2. promise的状态初始promise对象状态为pending、状态只能改变为rejected或者resolved,而且只能改变一次。无论变为成功还是失败, 都会有一个结果数据。 成功的结果数据一般称为 value, 失败的结果数据一般称为 reason。
3. promise的基本使用3.1 基本编码1234567891011121314151617181920212223242526// 1) 创建 promise 对象(pending 状态), 指定执行器函数const p = new Promise((resolve, reject) => { // 2) 在执行器函数中启动异步任务 setTimeout(() => { const time = Date.now() // 3) 根据结果做不同 ...
随着浏览器应用领域的广泛,消息队列这种粗时间颗粒度的任务已经不能适应部分领域的需求。所以出现了一种新的技术——微任务。微任务可以在实时性和效率之间做一个权衡。
目前来看,基于微任务的技术有MutationObserver、Promise 以及以 Promise 为基础开发出来的很多其他的技术
1. 宏任务页面中大部分任务都是在主线程上进行的:
渲染事件(如解析 DOM、计算布局、绘制);
用户交互事件(如鼠标点击、滚动页面、放大缩小等);
JavaScript 脚本执行事件;
网络请求完成、文件读写完成事件。为了协调这些任务有条不紊地在主线程上执行,页面进程引入了消息队列和事件循环机制,渲染进程内部会维护多个消息队列,比如延迟执行队列和普通的消息队列。然后主线程采用一个 for 循环,不断地从这些任务队列中取出任务并执行任务。我们把这些消息队列中的任务称为宏任务。
WHATWG是这样定义消息循环机制的:
先从多个消息队列中选出一个最老的任务,这个任务称为 oldestTask;
然后循环系统记录任务开始执行的时间,并把这个 oldestTask 设置为当前正在执行的任务;
当任务 ...
简单排序算法开始之前,先提供一个JavaScript版本的对数器,供写排序算法测试。
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869// 测试的方法function testMethod(arr) { }//正确的方法function rightMethod(arr) { arr.sort((a, b) => a - b);}//随机数组生成器,size为最大长度,value为最大值function generateRandomArray(size, value) { //生成长度随机的数组 let arr = new Array(Math.floor((size + 1) * Math.random())); for (let i = 0; i < arr.length; i++) { ...
JavaScript是一种动态弱类型的语言(运行过程中检查数据类型、支持隐式类型转换)。JavaScript中的数据类型一共有八种:
了解这些类型之后,有三点需要注意一下:
typeof 检测 Null类型,返回object,历史遗留问题,为了兼容老的代码。
Object类型所有key都是字符串(ES6又引入了Symbol类型),所以加不加引号都可以。如果是数值,会被自动转为字符串。如果键名不符合标识名的条件(比如第一个字符为数字,或者含有空格或运算符),且也不是数字,则必须加上引号,否则会报错。
前七种类型是原始类型,最后的Object类型是引用类型。二者内存存储方式不同。
1. 内存空间JavaScript 的执行过程中, 主要有三种类型内存空间,分别是代码空间、栈空间和堆空间。代码空间主要是存储可执行代码的,后续会提到,目前重点关注栈空间和堆空间。
栈空间就是之前提过的调用栈,用来存储函数执行上下文。前面文章我们提过:执行一段代码,要先编译,并创建执行上下文,然后再按照顺序执行代码。
12345678function foo() { var a = ' ...