大前端周刊 第21期 (本期小编:李凡)

Show me the code

关于Promise对象容易忽视的几个问题

1.resolve后的执行情况

无论是 resolve, reject,都会将函数剩余的代码执行完

1
2
3
4
5
6
7
8
9
10
11
const promise = new Promise((resolve, reject) => {
console.log('mark 1');
resolve('hello world'); // reject('hello world');
console.log('mark 2');
});

promise.then(result => {
console.log(result);
}).catch(err => {
console.log(err);
});

2.调用 then 方法返回新的 Promise 对象

1
2
3
4
5
6
7
8
9
let promise1 = new Promise((resolve) => {
resolve('Hello world')
})

let promise2 = promise1.then()

console.log(promise1 === promise2) // false
console.log(promise1 instanceof Promise) // true
console.log(promise2 instanceof Promise) // true

3.串行执行和并行执行

  • 串行执行:有一堆 Promise 对象,它们的执行顺序是固定的,前一个 promise 执行完后,后一个 promise 才开始执行,比如数据库查询,它们往往有前后的因果关系。
  • 并行执行:有一堆 Promise 对象,它们的执行顺序是不固定的,没有前后因果关系,可以并发地去执行。
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
//串行方式一
const datum = [];
for(let i = 0; i < 10; i++) {
datum.push(i);
}

let serial = Promise.resolve();

for(let i of datum) {
serial = serial.then(data => {
console.log(data);
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log(i * 200 + " ms 后执行结束");
resolve("第 " + (i + 1) + " 个 Promise 执行结束");
}, i * 200);
})
});
}

//串行方式二 使用reduce
const datum = [];
for(let i = 0; i < 10; i++) {
datum.push(i);
}

datum.reduce((prev, cur) => {
return prev.then(data => {
console.log(data);
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log(cur * 200 + " ms 后执行结束");
resolve("第 " + (cur + 1) + " 个 Promise 执行结束");
}, cur * 200);
})
})
}, Promise.resolve(true));

并行执行很好解决,在 Promise中有 all 这个函数支持, Promise.all 方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。当多个 Promise 实例执行完后才去执行最后新的 Promise 实例。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const datum = [];
for(let i = 0; i < 10; i++) {
datum.push(i);
}

Promise.all(datum.map(i => {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log(i * 200 + " ms 后执行结束");
resolve("第 " + (i + 1) + " 个 Promise 执行结束");
}, i * 200);
})
})).then((data) => {
console.log(data);
});

如果不使用 Promise.all 这个方法的话,你也可以使用像 ES7 的 async/await

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const asyncFun = async () => {
const datum = []
for(let i = 0; i < 10; i++) {
datum.push(new Promise((resolve, reject) => {
setTimeout(() => {
console.log(i * 200 + 'ms 后执行结束')
resolve('第 ' + (i + 1) + ' 个 Promise 执行结束')
}, i * 200)
}))
}
const result = []
for(let promise of datum) {
result.push(await promise)
}
console.log(result)
}
asyncFun()

4 . 结合 async/await 编写同步代码

  • async/await 函数可以帮助我们彻底摆脱回调地狱的烦恼,用一种同步的方式来编写异步函数。
  • await 后面可以接数值,如果是异步请求的话可以接 Thunk 函数和 Promise 对象。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const timeout = (ms) => {
return new Promise((resolve) => {
setTimeout(() => {
resolve(ms + ' passed')
}, ms)
})
}

const asyncFunc = async () => {
const value1 = await timeout(2000)
console.log(value1)
const value2 = await timeout(2000)
console.log(value2)
}

asyncFunc()
console.log('now')

5 .resolved 状态的 Promise 不会立即执行

1
2
3
4
5
let i = 0;
Promise.resolve('resolved promise').then(() => {
i += 2
})
console.log(i) // 0

文章推荐

  • 别再拿奇技淫巧搬砖了
    技巧性的知识大家都有掌握,使用场景及方式是否合理也是个问题。
    文章总结了一些常见的编程技巧的利弊,希望对大家有所帮助。
  • 抓住数据的小尾巴 - JS浮点数陷阱及解法
    推荐:众所周知,JavaScript 浮点数运算时经常遇到会 0.000000001 和 0.999999999 这样奇怪的结果,如 0.1+0.2=0.30000000000000004、1-0.9=0.09999999999999998,很多人知道这是浮点数误差问题,但具体原因就说不清楚了。本文帮你理清这背后的原理以及解决方案,还会向你解释JS中的大数危机和四则运算中会遇到的坑。
  • 打造自己的JavaScript武器库
    作为战斗在业务一线的前端,要想少加班,就要想办法提高工作效率。这里提一个小点,我们在业务开发过程中,经常会重复用到日期格式化、url参数转对象、浏览器类型判断、节流函数等一类函数,这些工具类函数,基本上在每个项目都会用到,为避免不同项目多次复制粘贴的麻烦,我们可以统一封装,发布到npm,以提高开发效率。
  • 浏览器渲染引擎
    浏览器基础是前端知识网中的一个小分支,也是前端开发人员必须掌握的基础知识点。他贯穿着前端的整个网络体系,项目优化也是围绕着浏览器进行的。
  • 美化表单的CSS高级技巧
    通常前端业务离不开表单,而其本身的UI确实不太美观,文章通过一些选择器实现常用表单的美化,相信对有定制化表单需求的小伙伴有所帮助。
  • websocket服务器监控
    这篇文章解释了一个简单的例子,用NodeJS搭建一个服务器监控程序,核心是socket.io实现的real time通信,另外还有node.js的child_process模块来实现进程管理。从这个简单而有用的例子出发,可以去研究socket.io和child_process的深层用法。

招聘

TalkingData DTU 可视化团队招聘:

  • 资深前端工程师

简历投递:

1
2
const email = 'xiang.wang#tendcloud.com'.replace('#', '@');
console.log(email);

大前端周刊 第20期 (本期小编:杨齐)

Show me the code

前端工程化工具 Dawn (来自阿里云开源)

阿里云内部的前端构建和工程化工具,现已完全开源。它通过 pipeline 和 middleware 将开发过程抽象为相对固定的阶段和有限的操作,简化并统一了开发人员的日常构建与开发相关的工作。

特点

采用中间件技术,封装常用功能,易于扩展,方便重用
支持 pipeline 让多个 task 协同完成构建任务
简单、一致的命令行接口,易于开发人员使用
支持基于「中心服务」管理中件间和工程模板
支持搭建私有中心服务,并统一下发构建规则,易于团队统一管理

安装

1
$ npm install dawn -g

使用

1
2
3
4
5
6
7
8
9
10
11
# 1. 创建 & 初始化
$ dn init -t front

# 2. 开发 & 实时编译
$ dn dev

# 3. 语法检查 & 测试
$ dn test

# 4. 构建 & 打包
$ dn build

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 启动开发服务
dev:
- name: webpack
entry: ./src/.js
template: ./assets/.html
watch: true
- name: server
port: 8001

# 直接构建
buid:
- name: webpack
entry: ./src/.js
template: ./assets/.html

文档

使用入门: getting-started

配置Pipeline: pipeline.md

插件推荐

  • Frontend Tracker
    Frontend Tracker 可以发现前端页面的错误,并且用户察觉错误前将错误发送至指定服务器。

文章推荐

  • Node.js加密算法库Crypto
    用Node做web服务进行用户认证的场合下,经常需要对用户密码进行加密和解码的操作。Crypto是NodeJS的内置库,提供了必要的功能,值得学习收藏。

  • Web 应用内存分析与内存泄漏定位
    无论是分布式计算系统、服务端应用程序还是 iOS、Android 原生应用都会存在内存泄漏问题,Web 应用自然也不可避免地存在着类似的问题。虽然因为网页往往都是即用即走,较少地存在某个网页长期运行的问题,即使存在内存泄漏可能表现地也不明显;但是在某些数据展示型的,需要长期运行的页面上,如果不及时解决内存泄漏可能会导致网页占据过大地内存,不仅影响页面性能,还可能导致整个系统的崩溃。

  • 前端状态管理请三思
    有关前端状态管理的一篇文章,结合实际中的问题,实现一个好用的状态机。

  • 前端API备忘录
    好脑筋不如烂笔头,平时还是要多写,多记,推荐一个比较常用的前端API合集,忘得时候查一下,很方便

  • 性能优化之组件懒加载
    文章首先抛出实际场景遇到的性能问题,给出现象,然后分析问题,提出两个解决思路,最后梳理优化并产出通用的Vue 2.x 组件级懒加载解决方案(Vue Lazy Component )。

  • JavaScript 在 V8 中的元素种类及性能优化
    JavaScript 对象可以具有与它们相关联的任意属性。对象属性的名称可以包含任何字符。JavaScript 引擎可以进行优化的一个有趣的例子是当属性名是纯数字时,一个特例就是数组索引的属性。

  • Webpack 热更新实现原理分析
    在使用 Webpack 构建开发期时,Webpack 提供热更新功能为开发带来良好的体验和开发效率,该文分析关于webpack热更新技术的实现原理。

  • JavaScript Event Loop 机制详解与 Vue.js 中实践应用
    依次介绍了函数调用栈、MacroTask 与 MicroTask 执行顺序、浅析 Vue.js 中 nextTick 实现等内容

  • 从Chrome源码看浏览器如何加载资源
    本文通过源码层面解释了浏览器如何加载资源,解决了前端对浏览器加载资源有很多不确定性的困惑,非常实用。

  • sass语法总结
    CSS 本身是非常强大的,但随着样式表变大,变复杂,维护 CSS 变得越来越难。这时候预处理就有用了。Sass 是一种预处理,它能让你使用一些 CSS 中没有的特性,比如:变量,嵌套(nesting),混入(mixins),继承等。这些特性能让 CSS 变的容易维护。

  • HTTP中GET与POST的区别
    看这霸气的文章标题!快来看看和自己理解的是否一致吧

招聘

TalkingData DTU 可视化团队招聘:

  • 资深前端工程师

简历投递:

1
2
const email = 'xiang.wang#tendcloud.com'.replace('#', '@');
console.log(email);

大前端周刊 第19期 (本期小编:段扬帅)

Show me the code

HTML5 桌面通知(Notification API)

HTML5新增的桌面通知API:Notification API是用于向用户推送通知消息的API。
值得注意的是,该通知不管用户在不在当前标签页都会进行推送

权限

该API需要用户明确授权同意推送后,才能进行推送!
那么怎么才能知道用户有没有同意呢?

1
Notification.permission

返回值:granted(用户同意) 、 denied(用户拒绝) 、 default(用户还没有选择)

获取权限

Notification 对象提供了requestPermission():

1
2
3
Notification.requestPermission().then(function(permission) {
console.log(permission) // 返回用户的选择
});

推送

得到用户的许可后,就可以愉快的进行推送了

1
new Notification(title, options)

参数说明:
title: 通知的标题。 必传
options:通知的设置选项。 可选:

  • dir:默认值是auto, 可以是ltr或rtl,表示提示主体内容的水平书写顺序。
  • body:通知的内容。
  • tag:代表通知的唯一标识,相同tag时只会打开同一个通知窗口。
  • icon:要在通知中显示的图标的URL。
  • data:想要和通知关联的数据。
  • requireInteraction:通知保持有效不自动关闭,默认为false。
  • vibrate: 通知显示时候,设备震动硬件需要的振动模式。所谓振动模式,指的是一个描述交替时间的数组,分别表示振动和不振动的毫秒数,一直交替下去,例如[200, 100, 200]表示设备振动200毫秒,然后停止100毫秒,再振动200毫秒。
  • renotify: 布尔值。新通知出现的时候是否替换之前的。如果设为true,则表示替换,表示当前标记的通知只会出现一个。
  • silent: 布尔值。通知出现的时候,是否要有声音。默认false, 表示无声。
  • sound: 字符串。音频地址。表示通知出现要播放的声音资源。
  • noscreen: 布尔值。是否不再屏幕上显示通知信息。默认false, 表示要在屏幕上显示通知内容。
  • sticky: 布尔值。是否通知具有粘性,这样用户不太容易清除通知。默认false, 表示没有粘性。

关闭

Notification.close() 关闭通知

支持事件

onclick 点击触发
onerror 显示异常触发
onclose 消息关闭时触发
onshow 消息显示的时候触发

兼容性

移动端几乎都不支持,PC端大部分都支持,IE需要14.0版本以上

插件推荐

  • gpu.js
    gpu.js这个库会把你写的js编译成GLSL然后在GPU上执行,以达到加速的效果。并且,如果电脑不支持GPU,它还会当成普通的js执行。

文章推荐

  • 探索nodeJS事件机制源码 打造属于自己的事件发布订阅系统
    本文探索并解析了nodejs的event实现和设计原理,解释了“事件发布订阅模式”,详细介绍了eventEmitter的一些核心属性和方法。另外,还基于ES6语法,DIY了一个简单的事件订阅发布系统。

  • http请求的理解
    从tcp到http,从计算机网络来看一个http请求,理解前后端网络通讯

  • 深入认识vue-cli:能做的不仅仅是初始化vue工程
    有许多同学没有搞清楚vue-cli和vue工程之间的关系,导致没有充分发挥vue-cli的功能。在这篇文章中,我将从底层原理开始并结合几个例子,告诉大家vue-cli还能这样用

  • CSS Modules 用法教程
    在前端模块化大行其道的今天,开发者发布的开源模块,如何避免 CSS 样式被宿主页面的样式所覆盖是非常重要的问题。CSS Modules 加入了局部作用域和模块依赖,这恰恰是网页组件最急需的功能。

  • JavaScript 中的对象拷贝
    在 JavaScript 中拷贝一个对象可能会碰到各种各样的问题,本文详细描述了各种拷贝的方法及注意点

  • Vue 2.0 的数据依赖实现原理简析
    源码解析,一步一步讲解 vue 的响应式是如何实现的,信息量比较大。

  • 在js里写SQL
    在日新月异的前端领域中,前端工程师能做的事情越来越多,前端页面可能出现一些数据逻辑复杂的页面,传统的js逻辑处理起来比较复杂,因此需要引入新的东西来简化逻辑。

  • ES6 模块系统
    对于ES6的模块系统,文章首先是对严格模式的一些总结,然后是对export 和 import 展开总结性的说明了各种绑定方式。

  • Vue 项目架构设计与工程化实践
    作者详述了自己Vue搭建项目的过程:技术选型(Vue全家桶)->架构设计(不同层面的职责)->发布上线。整个过程较为详细,举例项目遇到的问题及解决方案,对于搭建项目有一定的参考价值。

  • 深入探讨前端组件化开发
    这几年,从陷入 “React、Vue 和 Angular 哪个性能好?”的争论,到现在的各个框架(库)的生态越来越完善,讨论性能差距已经没有价值了。而国内的前端娱乐圈,最火的就是 React 和 Vue 了,而 Angular 由于历史原因,在国内的占有率确实不高。

  • 打造丝般顺滑的 H5 翻页库
    翻页组件实现起来并不难,本文在此基础上进一步尝试打造丝般顺滑的效果,各种优化手段值得学习。

  • 使用Node+Koa2+Mysql搭建简易博客
    Koa2使用实例,从Koa安装到项目建立模版使用,代码很详细的项目实例。

招聘

TalkingData DTU 可视化团队招聘:

  • 资深前端工程师

简历投递:

1
2
const email = 'xiang.wang#tendcloud.com'.replace('#', '@');
console.log(email);

大前端周刊 第18期 (本期小编:包京京)

Show me the code

用Javascript学习数据结构之栈(Stack)

栈(Stack)是一种遵循后进先出(LIFO)的有序集合,较新的元素会靠近顶部,较旧的元素会在栈的底部。
接下来我们正式开始实现栈(Stack)。首先,建立一个Stack类:

1
2
3
function Stack() {
// 类内部定义Stack的属性和方法
}

属性:

  1. let items = []; //使用array来存储栈内的元素

方法:

  1. push(elements): 新增一个或者多个元素到栈的顶部
  2. pop(): 移除栈顶部元素,同时返回被移除的元素
  3. peek()或top(): 仅返回stack元素,不做任何修改
  4. isEmpty(): 检查栈是否为空?若无任何元素则返回true,反之返回false
  5. clear(): 清空栈内的所有元素
  6. size(): 返回栈的元素个数

1.push(elements)和pop()

由于我们使用array当做stack的存储方式,所以我们可以使用array内建的push(element)和pop()方式来实现LIFO的特性,让元素的新增和删除只能发生在尾端。

1
2
3
4
5
6
7
8
9
function Stack() {
let items = [];
this.push = function(element) {
items.push(element);
}
this.pop = function() {
return items.pop();
}
}

2.peek():

若是我们想知道栈中的最后一个元素(最顶端的元素),我们可以实现peek()方法,返回顶部元素

1
2
3
4
5
6
function Stack() {
let items = [];
this.peek = function() {
return items[items.length - 1];
}
}

3.isEmpty():

若我们想知道栈内是否还有元素,我们可以使用isEmpty()来判断

1
2
3
4
5
6
function Stack() {
let items = [];
this.isEmpty = function() {
return items.length === 0;
}
}

4.clear():

若我们想清空栈的话,可以使用clear()方法,将所有元素删除

1
2
3
4
5
6
function Stack() {
let items = [];
this.clear = function() {
items = [];
}
}

5.size():

通过size()方法我们可以取得栈的大小(共有几个元素)

1
2
3
4
5
6
function Stack() {
let items = [];
this.size = function() {
return items.length;
}
}

完整代码:

把上面各种方法放到一起

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
function Stack() {
var items = [];
this.push = function(element) {
items.push(element);
}
this.pop = function() {
return items.pop();
}
this.peek = function() {
return items[items.length - 1];
}
this.isEmpty = function() {
return items.length === 0;
}
this.clear = function() {
items = [];
}
this.size = function() {
return items.length;
}
// 加入打印方法
this.print = function() {
console.log(items.toString());
}
}

插件推荐

  • PhantomJS
    PhantomJS可以应用于下面这几个典型场景:无需浏览器的web测试,页面自动化操作,屏幕截图和网络监控等

文章推荐

  • Node.js的事件轮询Event Loop原理解释
    Event Loop是理解Node实现事件驱动、异步高并发服务的关键。这篇文章中解释了下面几个容易被忽略的点: 1. Node.js的底层其实也是有一个线程池的,用来执行各种堵塞操作。2. 一个Event loop的三个基本组件:事件队列、读取事件的轮询线程、以及线程池。3. 各个事件的回调函数是如何激活并执行的。

  • jsonp原理详解
    jsonp不是ajax的一个特例,哪怕jquery等巨头把jsonp封装进了ajax,也不能改变这一点!

  • this , apply , call , bind详解
    几个ES5 的坑,this是其中经常搞晕的一个,上一篇通俗且易理解的文章

  • 深入理解 Node.js Stream 内部机制
    知其然知其所以然,来了解一下nodejs stream内部机制。

  • 基于 Electron 开发客户端产品的体验
    基于 Electron 开发的产品非常多,文章主要是针对于如何入门 Electron,可以说是作者开发的总结;非常适合计划使用 Electron的开发者阅读。

  • babel到底该如何配置?
    大家都知道js作为宿主语言,很依赖执行的环境(浏览器、node等),不同环境对js语法的支持不尽相同,特别是ES6之后,ECMAScrip对版本的更新已经到了一年一次的节奏,虽然每年更新的幅度不大,但是每年的提案可不少。babel的出现就是为了解决这个问题,把那些使用新标准编写的代码转译为当前环境可运行的代码,简单点说就是把ES6代码转译(转码+编译)到ES5。

  • CSS 新的长度单位 fr 你知道么?
    本文介绍了 CSS Grid 规范中引入的一个新的长度单位 fr,我们一起来看看到底是怎么回事吧!

  • 使用 webpack 优化资源
    本片文章中主要是基于 webpack 打包,以 React、vue 等生态开发的单页面应用来举例说明如何从 webpack 打包的层面去处理资源以及缓存,其中主要我们需要做的是对 webpack 进行配置的优化,同时涉及少量的业务代码的更改。

  • SASS用法指南
    今年TalkingData团队将 CSS 预处理器切换到了 SASS,代码层面只是简单直接的做了风格转换,还没有挖掘出 SASS 更深入的能力。本周推荐一篇 SASS “基础”内容,推荐大家阅读和实践,以提升大家在 CSS 方面的编程能力。

  • VirtualDOM与diff(Vue实现)
    我们是不是可以把真实DOM树抽象成一棵以JavaScript对象构成的抽象树,在修改抽象树数据后将抽象树转化成真实DOM重绘到页面上呢?于是虚拟DOM出现了,它是真实DOM的一层抽象,用属性描述真实DOM的各个特性。当它发生变化的时候,就会去修改视图。

  • 多“维”优化——前端高并发策略的更深层思考
    一项指标的变好,总少不了相应优化策略的实施。优化并不是简单的一蹴而就,而是个不断迭代与推翻的过程。更深层的优化方案,往往是在某种思维策略之下,对问题场景和基本策略优缺的深刻理解后做出的当下最优的权衡结果——作者导读。

  • Egg 源码解析之 egg-cluster
    Node.js 进程只能运行在一个 CPU 上,而 egg 采用多进程模型,使多核 CPU 的性能发挥到极致,最大程度地榨干服务器资源,进而解决了该问题。egg-cluster 是用于 egg 多进程管理的基础模块,负责底层的 IPC 通道的建立以及处理各进程的通信,本文解析了实现原理,值得一看。

招聘

TalkingData DTU 可视化团队招聘:

  • 资深前端工程师

简历投递:

1
2
const email = 'xiang.wang#tendcloud.com'.replace('#', '@');
console.log(email);

大前端周刊 第17期 (本期小编:耿少真)

Show me the code

柯里化

柯里化就是函数和参数值结合产生一个新的函数,如下代码,假设有一个curry的函数:

1
2
3
4
5
6
7
function add(a, b) {
return a + b;
}

let add1 = add.curry(1);
console.log(add1(5)); // 6
console.log(add1(2)); // 3

怎么实现这样一个curry的函数?它的重点是要返回一个函数,这个函数有一些闭包的变量记录了创建时的默认参数,然后执行这个返回函数的时候,把新传进来的参数和默认参数拼一下变成完整参数列表去调原本的函数,所以有了以下代码:

1
2
3
4
5
6
7
Function.prototype.curry = function() {
let defaultArgs = arguments;
let that = this;
return function() {
return that.apply(this, defaultArgs.concat(arguments));
}
};

但是由于参数不是一个数组,没有concat函数,所以需要把伪数组转成一个伪数组,可以用Array.prototype.slice:

1
2
3
4
5
6
7
8
Function.prototype.curry = function() {
let slice = Array.prototype.slice;
let defaultArgs = slice.call(arguments);
let that = this;
return function() {
return that.apply(this, defaultArgs.concat(slice.call(arguments)));
}
};

复杂选择器的查DOM

如实现一个document.querySelector:

1
document.querySelector(".mls-info > div .copyright-content")

首先把复杂选择器做一个解析,序列为以下格式:

1
2
3
4
5
//把selector解析为
var selectors = [
{relation: "descendant", matchType: "class", value: "copyright-content"},
{relation: "child", matchType: "tag", value: "div"},
{relation: "subSelector", matchType: "class", value: "mls-info"}];

从右往左,第一个selector是.copyright-content,它是一个类选择器,所以它的matchType是class,它和第二个选择器是祖先和子孙关系,因此它的relation是descendant;同理第二个选择器的matchType是tag,而relation是child,表示是第三个选择器的直接子结点;第三个选择器也是class,但是它没有下一个选择器了,relation用subSelector表示。

matchType的作用就在于用来比较当前选择器是否match,如下代码所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function match(node, selector){
if(node === document) return false;
switch(selector.matchType){
//如果是类选择器
case "class":
return node.className.trim().split(/ +/).indexOf(selector.value) >= 0;

//如果是标签选择器
case "tag":
return node.tagName.toLowerCase() === selector.value. toLowerCase();

default:
throw "unknown selector match type";
}
}

根据不同的matchType做不同的匹配。

在匹配的时候,从右往左,依次比较每个选择器是否match. 在比较下一个选择器的时候,需要找到相应的DOM结点,如果当前选择器是下一个选择器的子孙时,则需要比较当前选择器所有的祖先结点,一直往上直到document;而如果是直接子元素的关系,则比较它的父结点即可。所以需要有一个找到下一个目标结点的函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function nextTarget(node, selector){
if(!node || node === document) return null;
switch(selector.relation){
case "descendant":
return {node: node.parentNode, hasNext: true};
case "child":
return {node: node.parentNode, hasNext: false};
case "sibling":
return {node: node.previousSibling, hasNext: true};
default:
throw "unknown selector relation type";
//hasNext表示当前选择器relation是否允许继续找下一个节点
}
}

有了nextTarge和match这两个函数就可以开始遍历DOM,如下代码所示:

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
function querySelector(node, selectors){
while(node){ // 遍历节点
var currentNode = node;
if(!match(node, selectors[0])){
node = nextElement(currentNode);
continue;
}
var next = null;
for(var i = 0;i < selectors.length;i++){
var matchIt = false;
do {
next = nextTarget(node, selectors[i]);
node = next.node;
if(!node){
break;
}
if(match(node, selectors[i+1])){
matchIt = true; // 有一个符合就继续
break;
}
} while (next.hasNext);
if(!matchIt) break;
}
if(matchIt && i === selectors.length - 1){
return currentNode; // 全部匹配完
}
node = nextElement(currentNode);
}
return null;
}

最外层的while循环和简单选择器一样,都是要遍历所有DOM结点。对于每个结点,先判断第一个选择器是否match,如果不match的话,则继续下一个结点,如果不是标签选择器,对于绝大多数结点将会在这里判断不通过。如果第一个选择器match了,则根据第一个选择器的relation,找到下一个target,判断下一个targe是否match下一个selector,只要有一个target匹配上了,则退出里层的while循环,继续下一个选择器,如果所有的selector都能匹配上说明匹配成功。如果有一个selecotr的所有target都没有match,则说明匹配失败,退出selector的for循环,直接从头开始对下一个DOM结点进行匹配。

插件推荐

Vue Area Linkage: 中国行政区联动选择器,省、市、区、街道联动选择

文章推荐

  • 换种方式解读this
    文中用一种全新的形式解读this的几种绑定形式,不论是新入门还是大牛都可以看看这种新的解读形式。

  • 谈谈 PostCSS
    现在的前端,javascript的发展有目共睹,框架林立。同时,html也是齐头并进,推出了HTML5标准,并且得到了普及。这样的发展却唯独少了一个角色?

  • 前端:常见的6种HTML5错误用法
    人们在标签使用中最常见到的错误之一就是随意将HTML5的

    等价于
    ——具体地说,就是直接用作替代品(用于样式)。

  • vuejs 路由基础入门实战操作详细指南
    Vue.js + vue-router 创建单页应用,是非常简单的。使用 Vue.js ,我们已经可以通过组合组件来组成应用程序,当你要把 vue-router 添加进来,我们需要做的是,将组件(components)映射到路由(routes),然后告诉 vue-router 在哪里渲染它们。

  • JavaScript专题之解读 v8 排序源码
    文章对于插入排序与快速排序原理、实现讲解非常详细,并且在 V8排序的源码进行了实例分析。

  • 从Vue.js源码看异步更新DOM策略及nextTick
    文章以实际问题为引,从源码入手,吸收别人的思路,一步步得到解决问题方案。首先,我觉得作者这种解决问题的方式以及刨根问底的精神首先值得我们学习;其次,文章总结的很到位,配合代码示例,让人清晰理解nextTick的实现。

  • 更快速的Web应用程序I / O和流数据操作
    使用流更改您读取,写入和处理数据的方式。根据您的用例,代码复杂度可能会增加。然而,流可以实现数据的高效处理,从而导致更好的存储器性能。

  • 使用Nuxt.js改善现有项目
    SPA 应用有其天生的问题:搜索引擎爬虫抓不到,无法满足 SEO 的需求。这可以可以通过 SSR 解决,Nuxt.js 是由一对法国的兄弟基于 vue 2.0 提供的 ssr 能力开发的框架,基于恰到好处的约定与配置,可以显著的降低开发者创建服务端渲染 web app 的门槛。

  • 浅析nodejs的http模块
    HTTP模块是Node内置的核心模块之一,node入门的课程都会讲,通过createServer就可以得到一个server对象,关于它内部实现的理解,可以帮助你提高技能。本文讲解了HTTP模块的大致流程,对一些关键点进行了充分的分析。

  • 数据模拟神器 easy-mock
    如何提高前端开发效率?当前端UI及逻辑都写完而后端接口还没有完成,怎样不打断开发进程? 因此一款简单、高效、可视化并能快速生成模拟数据 的在线mock服务诞生。

  • 如何使用koa2+es6/7打造高质量Restful API
    如今nodejs变得越来越火热,采用nodejs实现前后端分离架构已被多数大公司所采用。在过去,使用nodejs大家首先想到的是express.js,而发展到如今,更轻量,性能更好的koa已然成为主流不仅性能优异,它还支持async/await, 堪称回调地狱的终结者。

招聘

TalkingData DTU 可视化团队招聘:

  • 资深前端工程师

简历投递:

1
2
const email = 'xiang.wang#tendcloud.com'.replace('#', '@');
console.log(email);

大前端周刊 第16期 (本期小编:张成斌)

Show me the code

ES6中的class语法

JavaScript 语言中,生成实例对象的传统方法是通过构造函数。这种写法跟传统的面向对象语言(比如 C++ 和 Java)差异很大。ES6 提供了更接近传统语言的写法,引入了 Class(类)这个概念,作为对象的模板。通过class关键字,可以定义类。基本上,ES6 的class可以看作只是一个语法糖,它的绝大部分功能,ES5 都可以做到,新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。

Class Definition

ES6语法

1
2
3
4
5
6
7
8
9
10
class Shape {
constructor (id, x, y) {
this.id = id;
this.move(x, y);
}
move (x, y) {
this.x = x;
this.y = y;
}
}

ES5语法

1
2
3
4
5
6
7
8
var Shape = function (id, x, y) {
this.id = id;
this.move(x, y);
};
Shape.prototype.move = function (x, y) {
this.x = x;
this.y = y;
};

上面ES6代码定义了一个“类”,可以看到里面有一个constructor方法,这就是构造方法,而this关键字则代表实例对象。也就是说,ES5 的构造函数Shape,对应 ES6 的Shape类的构造方法。Shape类除了构造方法,还定义了一个move方法。注意,定义“类”的方法的时候,前面不需要加上function这个关键字,直接把函数定义放进去了就可以了。另外,方法之间不需要逗号分隔,加了会报错。

Class Inheritance

ES6语法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Shape {
constructor (id, x, y) {
this.id = id;
this.move(x, y);
}
move (x, y) {
this.x = x;
this.y = y;
}
}
class Rectangle extends Shape {
constructor (id, x, y, width, height) {
super(id, x, y);
this.width = width;
this.height = height;
}
}
class Circle extends Shape {
constructor (id, x, y, radius) {
super(id, x, y);
this.radius = radius;
}
}

ES5语法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
var Shape = function (id, x, y) {
this.id = id;
this.move(x, y);
};
Shape.prototype.move = function (x, y) {
this.x = x;
this.y = y;
};
var Rectangle = function (id, x, y, width, height) {
Shape.call(this, id, x, y);
this.width = width;
this.height = height;
};
Rectangle.prototype = Object.create(Shape.prototype);
Rectangle.prototype.constructor = Rectangle;
var Circle = function (id, x, y, radius) {
Shape.call(this, id, x, y);
this.radius = radius;
};
Circle.prototype = Object.create(Shape.prototype);
Circle.prototype.constructor = Circle;

上面的ES6代码定义了一个Rectangle类和一个Circle类,它们通过extends关键字,继承了Shape类的所有属性和方法。子类里都出现了super关键字,它在这里表示父类的构造函数,用来新建父类的this对象。子类必须在constructor方法中调用super方法,否则新建实例时会报错。这是因为子类没有自己的this对象,而是继承父类的this对象,然后对其进行加工。如果不调用super方法,子类就得不到this对象。对照ES5语法我们可以发现使用class语法更简洁明了。

插件推荐

这个chrome插件可以查看网站,包括但不限于web框架、web服务器、js框架、js图表插件、字体、CDN。可以很方便的查看你感兴趣的网站所使用的技术。直接在chrome扩展商店里面搜whatruns就能安装。

文章推荐

  • 美团外卖前端可视化界面组装平台
    前端如何才能提高生产效率,普遍的共识是要做到组件化开发,很多团队已经这样做了。虽然很多的产品已经实现了组件化开发,但不同产品间依然存在很多重复的劳动,比如登录框、导航等等。这里推荐一篇美团外卖在效率方面尝试的一个解决方案。

  • 如何处理 JavaScript 内存泄露
    讨论开发者容易忽视的重要主题 :内存管理。文章也提供一些关于如何处理JavaScript内存泄露的技巧。在SessionStack,我们需要确保不会造成内存泄露或者不会增加我们集成的Web应用的内存消耗。

  • 反击爬虫,前端工程师的脑洞可以有多大?
    关于反击爬虫,本文给了很多前端反爬虫例子;
    真的感叹为了反爬虫,前段工程师真的费尽心思,脑洞大开!

  • Promise 异步流程控制
    网页中预加载20张图片资源,分步加载,一次加载10张,两次完成,怎么控制图片请求的并发,怎样感知当前异步请求是否已完成?

  • 设计模式之观察者模式
    观察者模式是一种常用的设置模式。文中提供了多种实现观察者模式的方式,并带有调用方式。可作为实现观察者模式的源码和研究观察者模式使用。

  • 用 threejs 制作一款简单的赛车游戏
    通过学习本教程,可以熟悉 webglthreejs 相关的知识。

  • 使用 SRI 增强 localStorage 代码安全
    大部分 Web 应用从 localStorage 中获取缓存代码后,没有任何检测机制,直接执行。而 localStorage 是跨页面的,同域下任何页面有 XSS 漏洞,就可以被攻击者用来往 localStorage 写入恶意代码,可以使用 SRI 增强 localStorage 代码安全。

  • 浏览器缓存机制小结
    本文总结了浏览器缓存的基本机制,将各种情况分为:强缓存和协商缓存两种方式。对三组核心的HTTP请求以及响应头参数:cache-control和expire, last-modified和if-modified-since,etag和if-none-matched,做了清晰的解释,很好理解它们之间的区别、优先级等关系。

  • HTTP 缓存机制一二三
    作为前端,常与请求打交道,HTTP缓存应该作为基本知识储备。文章介绍了强缓存和协商缓存,响应头各个字段的含义简单了解下,具体业务需要后端配合设置。

  • 如何优雅的在 koa 中处理错误
    软件开发时,有 80% 的代码在处理各种错误。 ——某著名开发者 想让自己的代码健壮,错误处理是必不可少的。这篇文章将主要介绍 koa 框架中错误处理的实现(其实主要是 co 的实现),使用 koa 框架开发 web 应用时进行错误处理的一些方法。

招聘

TalkingData DTU 可视化团队招聘:

  • 资深前端工程师

简历投递:

1
2
const email = 'xiang.wang#tendcloud.com'.replace('#', '@');
console.log(email);

大前端周刊 第15期 (本期小编:郭俊兵)

Show me the code

  • 对象数组排序

概念:javascript实现多维数组、对象数组排序,其实用的就是原生的sort()方法,用于对数组的元素进行排序。

语法:arr.sort(by(‘xx’))

  • 参数介绍:

    • function, key
      使用回调函数,处理需要排序的对象key。
  • 返回值
    排序以后的数组。

    针对于偶尔需要前端排序的情况,可以使用该方式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 回调函数
function by(name) {
return function(o, p) {
let a;
let b;
if (typeof o === 'object' && typeof p === 'object' && o && p) {
a = o[name];
b = p[name];
if (a === b) {
return 0;
}
if (typeof a === typeof b) {
return a < b ? -1 : 1;
}
return typeof a < typeof b ? -1 : 1;
}
};
}

需要排序的 Array:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const employees = [{
name: 'George',
age: 32,
retiredate: 'March 12, 2014'
}, {
name: 'Edward',
age: 17,
retiredate: 'June 2, 2023'
}, {
name: 'Christine',
age: 58,
retiredate: 'December 20, 2036'
}, {
name: 'Sarah',
age: 62,
retiredate: 'April 30, 2020'
}];

通过 age 排序:

1
employees.sort(by('age'));

结果:

1
2
3
4
[{"name":"Edward","age":17,"retiredate":"June 2, 2023"},
{"name":"George","age":32,"retiredate":"March 12, 2014"},
{"name":"Christine","age":58,"retiredate":"December 20, 2036"},
{"name":"Sarah","age":62,"retiredate":"April 30, 2020"}]

到这里,对象数组排序就算基本实现了。那如何实现多个键值排序呢?意思就是先是对age排序,如果age相同,再比较name。
这时,我们可以进一步修改by函数,让其可以接受第二个参数,当主要的键值产生一个匹配的时候,另一个compare方法将被调用以决出高下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// by函数接受一个成员名字符串和一个可选的次要比较函数做为参数
// 并返回一个可以用来包含该成员的对象数组进行排序的比较函数
// 当o[age]和 p[age] 相等时, 次要比较函数被用来决出高下
function by(name, minor) {
return function(o, p) {
let a;
let b;
if (o && p && typeof o === 'object' && typeof p === 'object') {
a = o[name];
b = p[name];
if (a === b) {
return typeof minor === 'function' ? minor(o, p) : 0;
}
if (typeof a === typeof b) {
return a < b ? -1 : 1;
}
return typeof a < typeof b ? -1 : 1;
} else {
thro("error");
}
}
}

待排序数组:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const employees = [{
name: 'George',
age: 32,
retiredate: 'March 12, 2014'
}, {
name: 'Edward',
age: 17,
retiredate: 'June 2, 2023'
}, {
name: 'Christine',
age: 32,
retiredate: 'December 20, 2036'
}, {
name: 'Sarah',
age: 62,
retiredate: 'April 30, 2020'
}];
// 排序操作
employees.sort(by('age', by('name')))

结果:

1
2
3
4
[{"name":"Edward","age":17,"retiredate":"June 2, 2023"},
{"name":"George","age":32,"retiredate":"March 12, 2014"},
{"name":"Sarah","age":32,"retiredate":"April 30, 2020"},
{"name":"Christine","age":58,"retiredate":"December 20, 2036"}]

插件推荐

  • jsoneditor JOSN格式编辑器

    安装

    1
    npm install jsoneditor

    引入

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    import JSONEditor from 'jsoneditor/dist/jsoneditor';
    const container = document.getElementById('jsonEdit');
    container.innerHTML = '';
    const options = {
    mode: 'code',
    };
    const editor = new JSONEditor(container, options);
    // 添加数据
    editor.set(JSON);
    // 获取数据
    editor.get();

文章推荐

招聘

TalkingData DTU 可视化团队招聘:

  • 资深前端工程师
  • 前端实习生

简历投递:

1
2
const email = 'xiang.wang#tendcloud.com'.replace('#', '@');
console.log(email);

大前端周刊 第14期 (本期小编:陶明)

Show me the code

  • Set

语法:new Set([iterable])

  • 参数介绍:

    • iterable
      如果传递一个可迭代对象,它的所有元素将被添加到新的 Set中。如果不指定此参数或其值为null,则新的 Set为空。
  • 返回值
    一个新的Set对象。

    简单说一下为什么要用 Set,因为 Set中的值具有唯一性(划重点!!!)。
    唯一性!
    所以,我就用它来去重。
    嗯,对。
    只用来数组去重!!!

1
2
3
4
5
6
7
8
9
10
11
const arr = [1, 2, 3, 4, 5, 5, 4, 3, 2, 0];
const ArraySet = new Set(arr);

Array.from(ArraySet); // [1, 2, 3, 4, 5, 0]
[...ArraySet]; // [1, 2, 3, 4, 5, 0]

const emoji = ['↖', '💎', '↗', '♠', '↖', '😏', '💎', '😍', '😏',];
const emojiSet = new Set(arr);

Array.from(emojiSet) // ["↖", "💎", "↗", "♠", "😏", "😍"]
[...emojiSet] // ["↖", "💎", "↗", "♠", "😏", "😍"]

只能 Array?

1
2
const text = 'prototype';
new Set(text); // Set {"p", "r", "o", "t", "y", "e"} 我是 String Set的

上面说到它的返回值是一个对象
So, 它有自己属性及方法。

1
2
3
4
5
const arr = [1, 2, 3, 4, 5, 5, 4, 3, 2, 0];
const mySet = new Set(arr);

mySet.size; // 6 剩 6 个了
mySet.length; // undefined

都叫 ‘size’了,当然是它的个数啊,
没 length(手动痴呆脸)我就试试看而已…

1
2
3
4
5
6
7
8
9
10
11
12
const arr = [1, 2, 3, 4, 5, 5, 4, 3, 2, 0];
const mySet = new Set(arr);

/* 我要加个 10 */
mySet.add(10) // [1, 2, 3, 4, 5, 0, 10] 加上了!

/* 我要加个 1 */
mySet.add(1) // [1, 2, 3, 4, 5, 0] 233 加不上!说了 Set有唯一性了!

/* 我不要 0 了 */
mySet.clear(0) // undefined !!!
mySet.clear() // undefined !!!

刷出来算我输…
Set.prototype.clear(),没参数,调用就清空啦.

当然是可以删除了,开了一个好冷的笑话(故作镇定接着写…)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const arr = [1, 2, 3, 4, 5, 5, 4, 3, 2, 0];
const mySet = new Set(arr);

/* 我不要 0 了 */
mySet.delete(0) // [1, 2, 3, 4, 5] 删掉了!

/* 有 1 吗? */
mySet.has(1); // true 有的!

/* 有 2 吗? */
mySet.has(2); // true 有的!

/* 有 0 吗? */
mySet.has(0); // false 没有!刚才删了!

其实还有几个方法,
这里只是简单的说一下这个 Set 而已
你以为我结束了?
我再说最后一个!
嗯!
最后一个!
我保证!

1
2
3
4
/* 用 forEach 能干点什么? */
mySet.forEach(function(value) {
// use value do something ...
});

OK,能力有限…

插件推荐

文章推荐

  • JavaScript 工作原理:内存管理与常见内存泄露分析
    本系列文章皆着眼于深度解析 JavaScript 内部运行原理,而本文则重点讨论编程语言中常见的内存管理问题;并且还提出了对于处理常见的内存泄露的建议。

  • 可视化基础之散点图介绍
    这篇文章介绍了散点图的科学意义,推荐大家阅读学习。可视化是前端发展的一个大方向,可视化工程师除了技术实现之外,还应该学习各种图表所能表达的科学含义。感谢蚂蚁金服体验技术部同学们,整理了一整套科学规范的可视化图表“字典”,让大家详细了解每种图表背后的含义。扩展阅读:可视化基础

  • JS正则表达式完整教程
    非常详细的介绍了JS中和正则相关的知识,文章很长,适合慢慢研读

  • webpack:从入门到真实项目配置
    文章主要介绍webpack配置,由简入繁、逐步优化,从简单的打包为一个bundle到分离代码、抽离共同代码、按需加载代码、自动刷新,每一步都非常详细,适合初学者快速入门。

  • AR.js 初探
    AR技术(增强现实技术Augmented Reality,简称 AR),AR技术在Native中已经兴起了,并且市场上有许多成功的APP,但是对于JavaScript怎么来玩转AR呢?下面我来简单的给大家演示两个不同版本,不同场景的AR小例子。

  • 史上最全面、最透彻的BFC原理剖析
    介绍FC的概念是什么; BFC的约束规则;咋样才能触发生成新的BFC;BFC在布局中的应用:防止margin重叠(塌陷,以最大的为准); 清除内部浮动;自适应两(多)栏布局。

  • JS遇上IOT
    IOT是 Internet of Things 的缩写,字面翻译是“物体组成的因特网”,准确的翻译应该为“物联网”。凡是可以用 JavaScript 来写的应用,最终都会用 JavaScript ——Atwood 定律。逃不出这个定律,JavaScript 也能用于物联网开发了。本文介绍了使用 JavaScript 在 ruff 开发平台上的小实例,有树莓派的小伙伴可以尝试把玩一下。

  • 上手 Webpack ? 这篇就够了!
    文章系统的概述了 Webpack 从安装到配置以及插件等等;讲述的还是比较全面。对于使用 Webpack 来说,完全可以说是够用。

  • 实现一个简单的虚拟DOM
    现在的流行框架,无论React还是Vue,都采用虚拟DOM。文中介绍了虚拟DOM的实现原理,能帮助更好理解双向绑定实现。

招聘

TalkingData DTU 可视化团队招聘:

  • 资深前端工程师
  • 前端实习生

简历投递:

1
2
const email = 'xiang.wang#tendcloud.com'.replace('#', '@');
console.log(email);

大前端周刊 第13期 (本期小编:李丽娇)

Show me the code

  • 剩余参数

概念:剩余参数(rest parameter)语法允许我们将一个不定数量的参数表示为一个数组。
使用场景:在不确定参数个数的函数中,设置部分行参。
语法:

1
2
3
function(a, b, ...restArgs) {
// ...
}

示例:

1
2
3
4
5
6
7
8
function multiply(multiplier, ...theArgs) {
return theArgs.map(function (element) {
return multiplier * element;
});
}

var arr = multiply(2, 1, 2, 3);
console.log(arr); // [2, 4, 6]

说明:
剩余参数和 arguments 对象的区别:

  1. 剩余参数只包含那些没有对应形参的实参,而 arguments 对象包含了传给函数的所有实参。
  2. arguments 对象不是一个真实的数组,而剩余参数是真实的 Array实例,也就是说你能够在它上面直接使用所有的数组方法,比如 sort,map,forEach,pop。
  3. arguments 对象对象还有一些附加的属性 (比如callee属性)。
  • 逗号操作符

概念:逗号操作符 对它的每个操作数求值(从左到右),并返回最后一个操作数的值。
语法:expr1, expr2, expr3…
示例:

1
2
3
4
5
6
7
8
9
10
function a(num) {
console.log(num);
}

function b(num) {
console.log(num * 2);
}

a(1), b(1); // 1 2
b(1), a(1); // 2 1

小结:
逗号表达式最常用的地方是是用一句代码定义多个变量的场景。在许多大厂的源码中也被用在如上示例的函数调用。

解决方案

  • Trackingjs

js实现人脸识别,看这里:https://trackingjs.com,文章推荐板块中有成功的实践案例。

  • 图片渐进式加载

需求:在网速不好的情况下,网站上的某张图片用上向下一点点加载,用户体现不友好。希望先显示整张图片然后渐渐变清晰。
方案:使用渐进式加载的图片,详情见文章:渐进式jpeg(progressive jpeg)图片

  • Flex布局

自从有了flex布局,处女座的设计师再也不用担心内容没有中间对其或上下对齐了。图文详解flex语法,戳下文:Flex 布局教程-语法篇

工具和模块

作为前端童鞋,平时开发免不了和接口打交道,拿到接口后需要测试一下接口返回是否正常,这时最后有一款支持各种请求方式的模拟Http请求工具。现在来介绍一些一款解决这个问题的工具-Postman,Postman支持各种请求方式,支持添加各个请求头参数。对写接口或用接口的同学来说都是利器。

  1. 官网:https://www.getpostman.com/

  2. 推荐文章:Postman用法简介

文章推荐

  • 面向 Web 开发者的 VR 指南
    近日来,越来越多的浏览器添加了对于 VR 特性的支持,本文即是盘点下目前浏览器中 VR 技术发展的现状,并且对可用的 WebVR 相关 API 进行简要介绍。

  • 深入浅出基于“依赖收集”的响应式原理
    文章很透彻的解析了对于使用Object.defineProperty()实现的响应式原理;从一个简单的实例逐步分析响应式原理的具体思路。讲解响应式原理的文章很多,这篇还是很形象的。

  • 30 行 JavaScript 代码搭建神经网络
    数据科学部的同学推荐的一篇神经网络入门实践文章,这篇文章图文并茂的介绍了神经网络的基础知识:神经元、神经网络等。深入阅读:神经网络入门

  • 深入浅出DOM基础——《DOM探索之基础详解篇》学习笔记
    文章稍长,本文只论述DOM基础概念,不涉及DOM的一些事件原理机制,页面元素的操作和常用API的讲解以及兼容性事项,所以概念性东西比较多,稍微有点抽象。

  • 编写可维护代码之“中间件模式”
    中间件可以介入请求和相应的处理,是一个轻量级的模块,每个中间负责完成某个特定的功能。

  • 当我们学习 Node.js 时,我们在学习什么?
    大家都说学 Node.js 学 Node.js,到底是学它的什么呢?是学 JavaScript 这门语言,还是学 Node.js 的 API?还是学 Node.js 各种三方库?

  • 石墨表格之 Web Worker 应用实战
    JavaScript 执行是单线程的,如运行 CPU 密集型任务会阻塞线程,此时浏览器会被卡住。解决该问题的办法之一就是引入Web Worker。Web Worker 为前端带来了后台计算的能力,可以实现主 UI 线程与复杂计运算线程的分离,从而极大减轻了因计算量大而造成 UI 阻塞而出现的界面渲染卡、掉帧的情况,从而更大程度地的提高我们的页面性能。

  • 那些你不能错过的 GitHub 插件和工具
    既然 GitHub 这么重要,又被我们使用得这么频繁,那关于 GitHub 的一些优秀浏览器插件或者其他工具,我们就一定不可错过啦。本文就来整理一些,都是我平常使用最得心应手的东西,全都倾力推荐出来,绝对干货!

  • 纯前端实现人脸识别-提取-合成
    前段时间火遍朋友圈的军装照竟然是用纯前段实现的!
    实现原理已在文中揭秘,速度get起来~

  • 实现精准的流体排版原理
    文章介绍了如何实现精准的流式排版。其中原理非常的简单,通过CSS的Viewport单位和calc()配合一些数学公式,较为精准的实现随着视窗改变,能较为精准的改变font-size的大小,甚至只要是带有长度单位的属性都可以通过这样方式,达到精准的值。

招聘

TalkingData DTU 可视化团队招聘:

  • 资深前端工程师
  • 前端实习生

简历投递:

1
2
const email = 'xiang.wang#tendcloud.com'.replace('#', '@');
console.log(email);

大前端周刊 第12期 (本期小编:李志伟)

Show me the code

  • 回调地狱

需求:异步读取多个文件,等到所有文件读取完毕执行特定操作。
简单实现:

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
// bad
fs.readFile('./config/test.txt'), (err, data) => {
if (err) throw err
fs.readFile('./config/test1.txt'), (err, data1) => {
if (err) throw err
fs.readFile('./config/test2.txt'), (err, data2) => {
if (err) throw err
fs.readFile('./config/test3.txt'), (err, data3) => {
if (err) throw err
console.log('success');
}
}
}
}

// good
function asyncReadFile (filePath, options) {
return new Promise((resolve, reject) => {
fs.readFile(filePath, options, (err, data) => {
if (err) reject(err);
resolve(data);
});
});
}

asyncReadFile('./config/test.txt').then(data => {
return asyncReadFile('./config/test1.txt');
}).then(data => {
return asyncReadFile('./config/test2.txt');
}).then(data => {
return asyncReadFile('./config/test3.txt');
});

小结:Promise 是一种对异步操作的封装,在异步操作执行成功或者失败时执行指定方法。将横向的异步调用转换为纵向,因此更符合人类的思维方式。

  • async和await

小小面试题:每隔一秒输出一个数字,顺序是:0 -> 1 -> 2 -> 3 -> 4 -> 5

简单实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 你首先想到的可能是这样
for (var i = 0; i < 5; i++) {
(function(j) { // j = i
setTimeout(function() {
console.log(new Date, j);
}, 1000);
})(i);
}
console.log(new Date, i);

// 利用es7的async和await 你还可以这样
const sleep = (timeountMS) => new Promise((resolve) => {
setTimeout(resolve, timeountMS);
});

(async () => { // 声明即执行的 async 函数表达式
for (var i = 0; i < 5; i++) {
await sleep(1000);
console.log(new Date, i);
}

await sleep(1000);
console.log(new Date, i);
})();

工具和模块

推荐简单易用的git客户端管理工具——Source Tree,支持创建、克隆、提交、push、pull 和合并等操作,其最大优点是拥有可视化界面,大大简化了开发者与代码库之间的Git操作方式,这对于那些不熟悉Git命令的开发者来说非常实用。

  1. 官网:https://www.sourcetreeapp.com/

  2. git学习教程:https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000

文章推荐

  • 从攻击看防御-前端视野下的web安全思考
    文章基于笔者对自身业务的web安全梳理,引起对web安全的一定思考。因其岗位视野以web前端为主,在对web安全的思考上,难免会有一定的局限性,故题目加上了“前端视野下”这样的修饰词。

  • 高性能滚动 scroll 及页面渲染优化
    本文算是对上一期关于函数节流与防抖的实际场景中的实践,阅读本文以助于更好好的理解函数节流与防抖,并且本文也提供了一些其他的优化思路。

  • 基于koajs的前后端分离实践
    要实现前后端分离框架,无非要满足这样几点:
    更便捷地创建路由、更高效地代理数据请求、更灵活地环境部署

  • 深入理解CSS时序函数
    本文非常详细的介绍制作动画时所使用的时序函数,对于动画的实现有详细的demo和说明。总之对于CSS动画来说,还是要看大家怎么玩这些属性了。

  • Webpack 的静态资源持久缓存
    代码每次更新->服务器重新部署->客户端重新下载资源,显然低效。所以这就是浏览器会缓存静态资源的原因,但存在缺陷:文件不修改文件名,浏览器会认为没有更新,就会使用缓存中的版本。文章介绍webpack如何配置以开启静态资源的持久缓存,内置详细代码示例,易懂易用。

  • js 深拷贝 vs 浅拷贝
    主要讲一下 js 的基本数据类型以及一些堆和栈的知识和什么是深拷贝、什么是浅拷贝、深拷贝与浅拷贝的区别,以及怎么进行深拷贝和怎么进行浅拷贝。

  • 关于HTTP协议
    http协议作为连接浏览器和服务器之间的协议,有着重要的作用,为前端开发必了解内容之一。
    下文介绍了http的概要,偏理论,可作为了解。

  • 前端校招面试该考察什么?
    文章总结了腾讯的校招流程和校招(实习生)对候选人技能的侧重方面。除了招聘,文章还对前端工程师的技术栈做了非常全面的总结。

招聘

TalkingData DTU 可视化团队招聘:

  • 资深前端工程师
  • 前端实习生

简历投递:

1
2
const email = 'xiang.wang#tendcloud.com'.replace('#', '@');
console.log(email);