0%

第2章 有意义的名称

2.2 名副其实

  • 变量 函数或类的名称都应该已经回复了所有的大问题。它应该告诉你,它为什么会存在,它做什么事,应该怎么用。如果名称需要注释来补充,那就不算是名副其实。
    阅读全文 »

1.字号与行高

字号大小就是字体的高度,如字号为50px,那么他的高度如下图:
font-size

行距为行高减去字号大小,如下图:
fontSizeAndLineHeight
所以 半行距 = (lineHeight-fontSize) / 2;

阅读全文 »

总的来说浏览器要经过一下几个步骤才能将下载好的数据渲染到浏览器界面上

DOM + CSSOM = Render Tree

  • 处理 HTML 标记并解析为 DOM 树。(Parse HTNL)
  • 处理 CSS 标记并解析为 CSSOM 树。(Recalculate style)
  • 将 DOM 与 CSSOM 合并成一个渲染树。
  • 根据渲染树来布局,以计算每个节点的几何信息。(layout)
  • 将各个节点绘制到屏幕上。(panit & Composite Layers )
    dom-css
    阅读全文 »

本文主要是基于浏览器标准(html5)介绍macrotask和microtask. 由于事件循环和执行环境相关所以在node中执行结果稍有不同。

首先了解我们知道js的特性是单线程、非阻塞I/O,不用考虑并发,死锁等问题。但是js的执行会导致多个线程同时在跑,如我们同时触发了异步http请求线程,以及定时器线程,如何管理他们之间的关系就需要even-loop。

1:首先我们的js线程在调用栈中触发了各种异步线程
2:异步线程执行完毕后放到异步任务对应源的队列中(Queue)
3:最后由event-loop将队列中(Queue)需要执行的任务按照一定策略取到js调用栈中执行

event-loop

接下来就是event-loop的执行的一些细节(html标准),大概分三步

1: 执行最旧的task(一次)
2:检查是否存在microtask,然后不停执行,直到清空队列(有可能多次)
3:检测是否执行render,如果可以就执行
flow

  • 一个线程中,事件循环(event-loop)是唯一的,但是根据任务源(tasks source)做区分的任务队列(tasks queued)可以拥有多个。

  • 任务队列又分为macrostask(宏任务)与microtask(微任务),在最新标准中,它们被分别称为task与jobs。

  • macrotask大概包括:script(整体代码), setTimeout, setInterval, setImmediate, I/O, UI rendering, networking(如ajax,fetch)。

  • microtasks大概包括: process.nextTick, Promise, Object.observe(已废弃), MutationObserver(html5新特性)

  • 在每个macrotask(宏任务)也就是task执行之间浏览器也许会更新渲染:原因是60fps(60 frame per second),这意味着约16.7ms进行一次render,如果task间隔没超过这个时间也就不会更新。

  • 在执行macrotask(宏任务)的时候遇到一个新的macrotasks(宏任务)会将任务分发到对应队列中等待下一次事件循环执行

  • mircrotask在两种情况会执行
    1在回调函数中函数栈没有正在执行中的其他js
    2在每个task的后面

  • 处理 microtask 队列期间,新添加的 microtask 添加到队列的末尾并且也被执行

  • 来自不同任务源的任务会进入到不同的任务队列。其中setTimeout与setInterval是同源的。

  • 在每一次事件循环(event-loop)中,macrotask 只会提取一个执行,而 microtask 会一直提取,直到 microtask 队列清空。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
console.log('glob1');
setTimeout(function() {
setTimeout(function(){
console.log('test1');
Promise.resolve().then(function(){
console.log('test1_promise')
});
});
console.log('timeout1');
new Promise(function(resolve) {
console.log('timeout1_promise');
resolve();
}).then(function() {
console.log('timeout1_then')
});
})

new Promise(function(resolve) {
console.log('glob1_promise');
resolve();
console.log('glob2_promise');
}).then(function() {
console.log('glob1_then')
}).then(function(){
Promise.resolve().then(function(){
console.log('glob1_then_test')
});
});

// glob1
// glob1_promise
// glob2_promise
// glob1_then
// glob1_then_test
// timeout1
// timeout1_promise
// timeout1_then
// test1
// test1_promise

分析下上面执行的结果:
1: golb1 第一个task(js script)中执行的同步console
2: glob1_promise 第一个task(js script)中执行promise构造函数的同步console
3: glob2_promise 第一个task(js script)中执行promise构造函数的同步console
4: glob1_then 第一个task执行完毕后检测先microtask队列中有一个Promise
5: glob1_then_test 第4步Promise执行过程中插入的microtask,也会继续执行
6: timeout1 执行第二个task(setTimeout)里面的同步console
7: timeout1_promise 第二个task中执行Promose构造函数的console
8: timeout1_then 第二个task执行完毕后检测microtask队列中有一个Promise
9: test1 第三个task(setTimeout)中同步执行的console
10: test1_promise 第三个task执行完毕后检测microtask队列中的Promise

解构

对象和数组字面量是js中最常用的标记,并且多亏JSON数据格式的流行它们成为了这面语言重要的一部分。对于定义对象和数组时相当常见的,同样从这些结构中系统的取出需要的部分也是同样常见。ES6为了简化这个过程添加了destructuring(解构:将大数据结构分解为很多小数据结构的过程)。这种中将为你展示如何使用在对象和数组上使用解构。

阅读全文 »

对象功能扩展

ES6在改进对象能力上花了很多的功夫,这是因为基本大部分js的值都是某种类型的对象,另外随着js应用程序复杂程度的提升代码中对象数量也随之提升。这也意味着对象需要更加高效的使用。

ES6通过各种方法改进对象,从简单的语法扩展再到提供更多选择处理对象。

阅读全文 »

函数

函数在任何语言中都是相当重要的一部分,在ES6之前,js的函数从这门语言被创建起就没有改变过。它留下了一些列问题和怪异行为从而直接导致了更加容易出错和实现基本的功能需要更多的代码。

阅读全文 »

字符串与正则表达式

字符串无疑在编程中最重要的类型之一,它们几乎出现在每个高级程序语言中,并且能高效的运用它们是开发者创造有用程序的基础,甚至于正则表达能给开发者额外的能力使用字符串也变得非常重要。记住这些事实以后,ECMAScript6的创建者通过对字符串和正则增加新属性和长久以来缺失的方法来达到提升。这章中我们将一一浏览这两种改变。

阅读全文 »

块绑定(Block Bindings)

以前在javascript中变量声明是比较复杂的一部分,大多数基于c的语言中变量(或绑定)被创建于变量声明的地方,然而javascript中并不是这样,变量创建的方式取决于你如何声明它们,并且ECMAScript 6 提供的了让控制作用域(scope)更容易的方法,在这章里将会展示为什么老式 var 声明让人困惑,同时介绍SCMAScript 6中的块绑定,并提供最佳实践。

阅读全文 »