GithubHelp home page GithubHelp logo

linhe0x0.github.io's People

Contributors

linhe0x0 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

linhe0x0.github.io's Issues

通过 CSS 实现六边形效果

故事说起那是在一个冰冷幽暗的晚上,外面下着淅淅沥沥的小雨,我正在思考一个十分重要的人生问题:这个周末哪里去?是宅在家里写程序好呢,还是宅在家里写博客好呢?还是好呢?这时,桌面右下角很少抖动的 QQ 头像竟然动了起来,我多年的直觉告诉我,一定是有人要约我,尽管这件事情从来没有发生过。我去,了不得,竟然是万年隐身的女神主动联系我,女神一定是因为看了朋友圈的照片对我的身材陷入了深深的迷恋,说不定还要保养我呢,啊,想想都觉得好激动啊~

“哎,在干嘛呢?” (你看,果然要约我)

“没事啊,在思考人生呢”

"那个,我在写一个网站,需要用 CSS 实现一个六边形效果,你能帮我写个 Demo 么?"

额。。。那个,好吧,跟想象中的有点不太一样,咦,万一这是女神对我的考验呢,说不定通过了之后就,哇卡卡~

用 CSS 实现一个六边形还不简单?

如下图,这就是我们要实现的六边形。

六边形

咋一看,这货怎么能用 CSS 来实现嘛?看官别着急,我给你画两条线你就能猜到了,请看下图:

六边形

咦,还没看出来?那您老再看下面这张图:

六边形

这下能够看出来了吧,没错,思路很简单,就是利用两个三角形和一个长方形然后拼接到一块,就能做出这么一个正六边形啦~

嗯?三角形怎么做?介个,等我什么时候有空了再给你娓娓道来吧(不过我想我是没空了,因为等我做完女神就要约我了~)

好了,废话不多说,直接上代码~ 点击查看

然后痛痛快快的给女神发了过去,

"咦,效果虽然是这个效果,但是为什么鼠标移入的触发区域不太对呢?能不能把鼠标移入的触发区域也仅限制为六边形?"

嗯,这确实是这种方法的一个弊端,因为 CSS 中是没法直接做一个三角形的,所以我们利用了 border 的特点模拟了一个出来,但是元素本质上还是一个矩形。

那么问题来了,怎样实现一个完美的六边形效果呢?

哈哈,这个问题怎么能难得住我嘛,不多一会,我就做出了一个完美的六边形出来给女神发过去了,这次主要是利用了 overflow: hidden 和 CSS3 中的 transform 相关属性实现的。详细代码请 点击查看

嗯,这次看来女神挺满意的~

毕竟鼠标移入的触发区域也完美的限制在六边形里面了嘛~

女神表达了感激之情,我们在 QQ 上轻(gan)松(ga)的聊了起来,看起来是到了该约周末一起吃饭的时候了。

"啊,抱歉噢,我周末要跟男朋友一起去逛街呢"

哦。

呵呵哒。

真是一个感(lei)人(jue)肺(bu)腑(ai)的爱情故事。

[译] 一个关于 Styled Components 的五分钟介绍

CSS 是一个很神奇的语言,你可以在 15 分钟之内就学会一些基础部分,但是如果你要找到一个好的方式来组织你的样式,将会花费数年时间。

这主要是由于语言本身很奇葩。不合常规的是, CSS 是相当有限的,没有变量、循环或者函数。与此同时,它又是相当自由的,你可以随意使用元素、Class、ID 或它们的任意组合。

混乱的样式表

正如你自己所经历过的那样,CSS 通常是很混乱的。虽然有诸如 SASS 和 LESS 这样的预处理器添加了大量有用的特性,但是它们仍然不能阻止 CSS 的这种混乱状态。

组织工作留给了像 BEM 这样的方法,这些方法虽然很有用但是完全是自选方案,不能在语言或工具级别强制实施。

CSS 的新浪潮

最近一两年,新一波基于 JavaScript 的工具正试图通过改变编写 CSS 的方式来从根本上解决这些问题。

Styled Components 就是那些工具库之一,因为兼顾创新和传统的优势,它很快就吸引了大量的关注。因此,如果你是 React 使用者(如果你不是的话,可以看看 我的 JavaScript 学习计划 和我写的 React 简介),就绝对值得看看这个新的 CSS 替代者。

最近我用它 重新设计了我的个人网站,今天我想分享下我在这个过程中所学到的一些东西。

组件, 样式化

关于 Styled Components 你需要理解的最主要的事情就是其名称应该采取字面意思。你不再根据他们的 Class 或者 HTML 元素来对 HTML 元素或组件进行样式化了。

<h1 className="title">Hello World</h1>

h1.title {
  font-size: 1.5em;
  color: purple;
}

相反,你可以定义一个拥有它们自己的封装风格的 styled Components。然后你就可以在你的代码中自由的使用它们了。

import styled from 'styled-components';

const Title = styled.h1`
  font-size: 1.5em;
  color: purple;
`;

<Title>Hello World</Title>

这两段代码看起来有一些细微的差别,事实上两者语法是非常相似的。但是它们的关键区别在于样式现在是这些组件的一部分啦。

换句话说,我们正在摆脱 CSS class 作为组件和其样式的中间步骤这种情况。

styled-components 的联合创造者 Max Stoiber 说:

styled-components 的基本**就是通过移除样式和组件之间的映射关系来达到最佳实践。

减少复杂性

这首先是反直觉的,因为使用 CSS 而不是直接定义 HTML 元素的关键点(还记得 <font> 标签吗?)是引入 class 这个中间层来解耦样式和标签。

但是这层解耦也创造了很多复杂性。有这样一个的观点:相比于 CSS,诸如 Javascript 这类『真正』的编程语言具备了更好的处理这种复杂性的能力。

类(Class)上的 Props

为了遵循 『无类(no-class)』的理念,当涉及到自定义一个组件的行为时,styled-components 使用了类上的 props(props over classes)。所以呢,代码不是这样的:

<h1 className="title primary">Hello World</h1> // will be blue

h1.title{
  font-size: 1.5em;
  color: purple;

  &.primary{
    color: blue;
  }
}

你需要这样写:

const Title = styled.h1`
  font-size: 1.5em;
  color: ${props => props.primary ? 'blue' : 'purple'};
`;

<Title primary>Hello World</Title> // will be blue

正如你所看到的那样,styled-components 通过将所有的 CSS 和 HTML 之间的相关实现细节(从组件中)分离出来使你的 React 组件更干净。

也就是说,styled-components 的 CSS 仍然还是 CSS。所以像下面这样的代码也是完全有效的(尽管略微不常用)。

const Title = styled.h1`
  font-size: 1.5em;
  color: purple;

  &.primary{
    color: blue;
  }
`;

<Title className="primary">Hello World</Title> // will be blue

这是让 styled-components 很容易就被接受的一个特性:当存在疑惑时,你总是可以倒退回你所熟悉的领域。

警告

需要提到的很重要的一点是 styled-components 仍然是一个很年轻的项目。有一些特性到目前为止还没有完全支持。例如,如果你想 从父组件中样式化一个子组件 时,目前你仍不得不依靠 CSS class 来实现(至少要持续到 styled-components 版本 2 发布)。

目前也有一个非官方的方法来实现 服务端预渲染你的 CSS,虽然它是通过手动注入样式来实现的。

事实上,styled-components 生成它自己的随机 class 名会使你很难通过浏览器的开发工具来确定你的样式最初是在哪里定义的。

但是鼓舞人心的是,styled-components 核心团队已经意识到了这些问题,并且努力地一个又一个的攻克它们。版本 2 很快就要来啦,我真的很期待它呢。

了解更多一点吧

我这篇文章的目的不是向你详细解释 styled-components 是如何生效的,更多的是给你一个小瞥。所以你可以自己决定是否值得一试。

如果我的文章让你感到好奇的话,这里有一些链接你可以了解更多关于 styled-components 的知识。

如果你想更进一步,也可以了解下 Glamor —— 一个完全不同的 CSS 新浪潮。

谈谈 JS 中的严格模式

什么是严格模式?

严格模式 是 ECMAScript 5 中引入的一种将更好的错误检查引入代码中的方法, 现在已经被大多浏览器实现. 顾名思义,这种模式使得Javascript在更严格的条件下运行.

因此, 在严格模式下, 我们的一些不严谨的写法将会导致程序抛出错误. 例如:

function fn(param) {
    var arguments = []; // 在严格模式下该行将会抛出错误: error: redefinition of arguments
}

在上面的代码中, 由于 arguments 在 js 中是一个特殊对象, 在严格模式下是不允许被重新定义的. 但是没有实现严格模式检查的环境中会接受这段代码.

为什么会出现严格模式?

总所周知, 从 ECMAscript 从1997年正式成为国际标准以来, 已经发布了6个版本. 除此之外, 还存在一些 Javascript 实现支持非标准特性, 而其他的 Javascript 实现却并不支持这些特性的情况. 由于 Javascript 的实现多样化, 我们很难确定哪些特性在哪些平台上是支持的, 再加上 Web 浏览器的复杂性, 并且它并不能让开发者指定某一个特定的 Javascript 版本来执行我们的程序. 因此我们需要精心的编写程序, 以确保在所有的平台上都能够正常运行.

因此在 ES5 中引入了一种版本控制的考量: 严格模式. 此特性允许开发者选择在受限制的 Javascript 版本中禁止使用一些 Javascript 语言中问题较多或是易于出错的特性.

由于其语法强大的向后兼容特性, 所以即使在没有实现严格模式检查的环境中, 你的严格代码仍然可以正常执行.

如何使用严格模式?

在程序中使用严格模式的方式是在程序中的最开始增加一个特定的字符串字面量.

"use strict"

如果你在一个文件的顶部加入这个特定的字符串, 则表示该文件的所有内容将始终使用严格模式执行.

如果你只想在一个函数体内使用严格模式, 则在该函数体内的最开始处(顶部)加入这句指令.

为什么要使用字符串字面量来实现严格模式?

单独使用一个特定的字符串字面量来作为指令语法在语言里看起来确实相当怪异, 但是他有一个最大的好处是向后兼容. 我们来看一下它为什么能够向后兼容. 我们都知道在js 中解释执行一个字符串字面量是没有任何副作用的, 这句话什么意思呢? 比如说你在 chrome 浏览器控制台里面输入一个字符串字面量, 解释器只会返回一个同样的字符串, 除此之外不会发生任何事情, 这就使得即使ES3引擎不支持严格模式, 但依然能够无伤大雅的解释和执行这条指令. ES3 引擎在解析完改字符串之后, 会立即将该值丢弃. 因此, 尽管旧的引擎不支持严格模式, 但依然能够正常运行.

但需要注意的是: 尽管不会抛出错误, 但是旧的引擎不会进行任何的严格检查模式, 因此如果要使用严格模式, 你应该总是在完全兼容ES5的环境中测试严格代码.

使用严格模式需要注意哪些问题?

我们在上面已经说过, use strict 指令需要写在脚本或者函数的顶部, 因为该指令只有在写在顶部才能生效. 这就使得我们在使用的时候需要注意一下这里有个小坑. 这个坑是什么呢?

举个例子, 我们在开发大型功能的时候, 开发过程中会使用多个独立的脚本文件, 但是在部署到生产环境的时候出于性能优化的目的, 需要将多个脚本连接成一个单一的文件. 比如说, 脚本1 运行于严格模式下,

// file1.js 
"use strict"
function doSth() {
}

但是有另外一个同事写了一个脚本2运行于非严格模式下:

// file2.js
function doOtherSth(param) {
    var arguments = [];
}

那么, 我们该怎么连接这两个文件呢? 如果我们以 file1.js 开始, 那么连接后的代码将运行于严格模式下, 但是由于 file2 中的一些操作会在严格模式下抛出错误, 导致我们的程序无法正常运行.如果我们以 file2.js 开始, 那么连接后的代码将运行于非严格模式下, 因为我们前面已经讲过该指令只有在写在顶部才能生效. 似乎怎样都不太合适.

那么如何解决这个问题呢?

  1. 在项目中坚持只使用严格模式或者只使用非严格模式, 并且不要将使用严格模式和不使用严格模式的文件进行打包构建. O(∩_∩)O哈哈~这样就不会有问题了嘛.
  2. 我们上面说过, 如果你只想在一个函数体内使用严格模式, 则在该函数体内的最开始处(顶部)加入这句指令. 我们可以利用这个特性, 将每一个脚本文件里面的代码包裹在一个立即执行的函数表达式内, 这样即使两种模式的文件打包在一起, 依然能够按照我们的期望进行工作. 例如:
;(function() {
    // file1.js 
    "use strict"
    function doSth() {
    }
})();

;(function() {
    // file2.js 
    function doOtherSth() {
    }
})();

当然了, 上面这样的做法会导致这些文件的内容不会在全局作用域内解释, 这就导致我们通过 varfunction 声明的变量不会视为全局变量. 不过这刚好对我们来说也是一个很好的特性. 因此就放心大胆的使用吧, 去吧, 皮卡丘.

最佳实践

上面的方法2看起来是极好的, 并且我们可以通过自动化构建工具为我们的脚本文件上添加如上代码. 但是如果我们想要编写一个通用的库, 使其可以在尽可能多的环境中正常工作, 我们不能假设脚本文件一定会被构建工具置于一个立即执行的函数中, 也不能假设客户端代码一定处于严格模式或是非严格模式中. 所以为了获得最佳效果, 我们应该总是在严格模式下编写代码, 并显式的将其包裹在启用了严格模式的立即执行函数中, 而不是依靠构建工具来实现.

结语

"严格模式"体现了Javascript更合理、更安全、更严谨的发展方向. 为了达到更为普遍的兼容性, 我们应该总是在严格模式下编写代码.

前端开发书籍推荐目录

前几天有朋友说他们公司要做一个培训计划,让我给推荐几本关于前端方面的书籍,拖延了四五天之后,终于还是耐着性子把它写完了,这里也一并发出来,希望能够给那些在自学道路上艰难前行的人带来一点光亮和温暖。

以下是正文部分。

关于前端开发方面的书籍,我也看过那么几本,就简单的聊一下我看过的这些吧.

1、Head First HTML与CSS

这本书最大的优点就是除了基础还是基础,非常适合完全不知道前端开发是什么的门外汉作为第一本入门书籍来学习, 整本书采用插画和故事场景的形式叙述,和那些枯燥、深奥的HTML书籍完全不同,秉持了 Head First 系列一贯通俗易懂的风格。你看这本书的时候会发现就像是在看漫画书一样轻松。是我看过对初学者最友好的书,没有之一。

2、CSS 权威指南

在看了第一本书后,想必你已经对 HTML 和 CSS 的基础知识有了一定的了解,甚至你已经能够做出一些简单的网站了。但是你可能只是知道一些常见的 CSS 属性,毕竟上一本书只是讲解一些基础知识。所以如果你想要全面的、深入的了解 CSS ,那么权威指南系列是你的不二选择。

这是一本非常经典的 CSS 参考书,它的经典之处在于,它用普通人类可以理解的语言系统、全面地讲解了 CSS 规范。这本书会告诉你,CSS 是什么、CSS 有什么、CSS 可以做什么。

这本书就像是 CSS 里面的圣经一样,以神一般的地位存在。当然了,你不要被它的厚度给吓到,其实你在看这本书的时候完全不需要非要每一页都非常详细的看一遍,你只需要粗略的翻一下,了解一下内容,然后大部分情况下把它当做字典来使用。用一个知识点学一个知识点就好了。

3、精通 CSS

这同样是一本非常经典的 CSS 图书,它侧重于实践,告诉你如何正确地使用 CSS。

这本书将最有用的 CSS 技术汇总在一起,还总结了 CSS 设计中的极具实践,讨论了解决各种实际问题的技术,填补了一直以来 CSS 图书的空白。

作者多年来一直在编写、设计和宣传基于标准的网页设计,我们现在有幸在本书中看到他以简洁清晰的方式讲授最重要的 CSS 技术。本书提供了一套网页设计人员不可或缺的解决方案、技巧和经验。

4、CSS Secrets

大家可能注意到了,这两本都出版于 2006 年。而今年已经是 2016 年了。如果你的书架只能放得下三本 CSS 书,除了上面的那两本之外,我向你强力推荐的一定是这一本。

这本书的准确出版时间为2016年04月底,也就是说截止目前为止,这本书都还没有出版,那么我为什么要向大家推荐一部还没有出版的书籍呢?github 上有试读篇,感兴趣可以先看看,不管你是什么感受,反正我看完就跪着去下单了。

对于中级的 CSS 开发者来说,这本书可以发挥最大的功效——它可以帮助你进阶。相信很多开发者在学习 CSS 到了一定阶段的时候,感觉自己好像什么都会了,但遇到复杂问题时往往又感觉捉襟见肘、力不从心。这就是遇到瓶颈了。如何突破瓶颈、进入下一个阶段?要做的无非是两件事——实践和思考。书并不能代替你思考,但一本好书可以向你示范,什么样的思考方式是正确的。

5、图解 CSS3 (核心技术与案例实战)

这本书是手淘的大漠写的,大漠作为 W3cplus 创始人,一直专注对 CSS 方面尤其是 CSS3 的研究,是国内最早研究和使用CSS3技术的一批人。这本书算是他的呕心力作,在书中有趣且易懂的来描述了 CSS3 的每一个特性。不仅内容极为全面、详实,而且富含大量的案例,实用性非常强,如果你对 CSS3 非常感兴趣,那你就有福了。

6、Effective Javascript 编写高质量 Javascript 代码的 68 个有效方法

Effective 系列丛书经典著作,亚马逊五星级畅销书。就冲着这样的地位也值得入手。作者凭借多年标准化委员会工作和实践经验,深刻辨析JavaScript 的内部运作机制、特性、陷阱和编程最佳实践,将它们高度浓缩为极具实践指导意义的 68 条精华建议。内容很接地气,实用性很强,我表示看过之后受益颇深。无论你是刚学习 JS 的入门者,还是有着几年经验的开发者,这本书都值得你一看。

7、编写可维护的JavaScript

这是一本构建编码风格手册,帮助你和你的团队从“游击队”走向“正规军”的书籍。书中向开发人员阐述了如何在团队开发中编写具备高可维护性的JavaScript代码。覆盖了编码风格、编程技巧、自动化、测试等几方面。无论你是前端开发者还是团队 leader,无论你是刚入门的初学者还是有经验的开发者,都建议你阅读一下这一本书。

8、Javascript 高级程序设计

JavaScript 超级畅销书,技术经典名著。本书在详细讲解了JavaScript语言的核心之后,条分缕析地为读者展示了现有规范及实现为开发Web应用提供的各种支持和特性,全面深入、贴近实战的特点非常适合有一定编程经验但是想要进阶的开发者来学习。

9、Javascript 语言精粹

众所周知,Javascript 之父只用 10 天时间就把 Javascript 设计出来了。由于设计时间太短,语言的一些细节考虑得不够严谨。这个曾是“世界上最被误解的语言”,担负了太多的特性,包括糟糕的交互和失败的设计,但是现在,JavaScript 俨然从 “最受误解的编程语言” 演变为了 “最流行的语言”,这说明 Javascript 有其自身独特的魅力。本书剥开了 JavaScript 沾污的外衣,抽离出一个具有更好可靠性、可读性和可维护性的JavaScript 子集,让你看到一门优雅的、轻量级的和非常富有表现力的语言。说其是每一个 Javascript 开发者都必备的一本书一点也不为过。

10、Javascript 权威指南

权威指南系列想必已经不用多说了,各个都很经典,值得入手。这本书详细的讲解了 Javascript 中的各种语法和语言核心设计,覆盖了 JS 的核心 API、遗留的客户端API和W3C标准DOM API,记述了这些API中的每一个JavaScript对象、方法、性质、构造函数、常量和事件处理程序。不过由于其内容量过于庞大,建议平时作为字典使用即可。

如果你的书架只能放得下三本 �JS 书, 那么这三本已经凑齐了,我强烈推荐『Javascript 语言精粹』、『Javascript 高级程序设计』和这一本『Javascript 权威指南』。

11、Javascript 设计模式

这本也算是 O'REILLY 系列中的一个非常好的书籍,实际上 O'REILLY 系列基本上都没有差的。书中集中介绍了很多流行的设计模式在JavaScript中的应用以及实现方式。作为高级前端开发工程师学习设计模式的一本进阶书籍非常合适。

12、Javascript 设计模式与开发实践

这本书是由国内知名前端团队腾讯 AlloyTeam 成员编写的,设计模式自古乃程序员高谈论阔之话题,许多程序员从设计模式中学到了设计软件的灵感,或者是问题的解决方案。但是有些人却认为设计模式只适合静态语言,Javascript 这种动态语言根本就没有设计模式一说。显然,本书给了你最好的答案。

该书全面涵盖了 JavaScript 的 16 个常用的设计模式、设计原则、编程技巧和代码重构,由浅入深的详细介绍了面向对象的设计原则以及在设计模式中的体现。让你能够将经典的设计模式应用到 JS 中,实乃高级程序设计必读之佳作。

13、jQuery 技术内幕

阿里巴巴资深前端开发工程师墨智的大作,没出版之前我就一直在关注,渴望能偶早早看到。

jQuery 作为全球使用量最大的 JS 库,它的优秀想必我也不需要说了,如果你使用了多年的 jQuery,但一直不敢去了解它的源码实现方式,或者你觉得你的 JS 技能进入了瓶颈期,那这本书对你来说就如同雪中送炭一样。

本书首先通过“总体架构”梳理了各个模块的分类、功能和依赖关系,让大家对 jQuery 的工作原理有大致的印象;然后按照源码几乎逐行分析了其中各个模块的源码实现,分析的详细程度简直“令人发指”。不过这本书是基于 1.x 的版本进行分析的,阅读的时候略微注意即可,实际上即使是 1.x 版本的 jQuery,也非常值得我们学习。

14、数据结构与算法 Javascript 描述

这本书覆盖了常用的基本数据结构,如果你对数据结构很感兴趣,算是一本不错的入门书籍吧,推荐指数三颗星。但是本书中也有一些错误出现,建议看中文版的同时对照英文勘误表进行阅读和学习。

15、React 引领未来的用户界面开发框架

2014 年横空出世的由 Facebook 推出的开源框架 React.js,基于 Virtual DOM 重新定义了用户界面的开发方式,彻底革新了大家对前端框架的认识。在这个火热朝天的年代,如果你连 React 都还没听说过,那还是赶紧洗洗睡吧。如果你听说过但是没有使用过,或者是想要学习 React 但是该不知如何下手,再或者是看不懂那些晦涩难懂的英文文档,那么这本书就很适合你了。这本书介绍了 React 的一些基础知识,比较适合入门,但是前端开发的世界变化的这么快,估计这本书的生命周期也没几年吧。

16、HTML5 游戏开发进阶指南

这本书介绍了 HTML5 游戏开发的一般过程和技巧,如果你对 HTML5 游戏开发很感兴趣,可以看一下。并且书中也有很多的案例,作为一个学习游戏开发的入门书籍还是可以的。

17、深入浅出 Nodejs

开发者的大事,大快所有人心的大好事。

出自国内阿里大神朴灵的大作,国内最好的 Nodejs 书籍,没有之一。同时也是第一本深度讲解 Node 的图书。本书从不同的视角介绍了 Node 内在的特点和结构。非常适合想要深入了解学习 Nodejs 的高级开发者来学习。实际上,不管是否学习过 Node,只要你热爱技术,都推荐你阅读它。

18、HTTP 权威指南

谁说做前端开发不需要了解 http 相关知识?高级前端开发者永远不会仅仅满足于了解 ajax 是怎么回事之后就止步不前,如果你想要学习 http 和通信协议相关的知识,那就不要再犹豫了,一定是这本书了。

书中尝试着将HTTP中一些互相关联且常被误解的规则梳理清楚,并编写了一系列基于各种主题的章节,对HTTP各方面的特性进行了介绍。书中对HTTP“为什么”这样做进行了详细的解释,而不仅仅停留在它是“怎么做”的。非常适合作为高级开发者进阶学习之资料。

19、黑客与画家

这本书就比较特殊了,这本是硅谷创业之父Paul Graham 的文集,注意,是文集,而不是像上面那些那样是技术书籍。

这本书主要介绍黑客的爱好和动机,讨论黑客成长、黑客对世界的贡献以及编程语言和黑客工作方法等所有对计算机时代感兴趣的人的一些话题。书中的内容不但有助于了解计算机编程的本质、互联网行业的规则,还会帮助读者了解我们这个时代,迫使读者独立思考。

简单的来说,这是一本谈论编程哲学的书籍,而不是针对某种语言进行解释的技术书籍。

本书适合所有的程序员和互联网工作者,以及一切对计算机感兴趣的人阅读。

GitBook 简明教程

Modern book format and toolchain using Git and Markdown

这是 GitBook 项目主页上对 GitBook 的定义。

GitBook 是一个命令行工具。通过它,你能够使用 Git 和 Markdown 来编排书本。并且通过工具可以自动生成相应的 HTML、PDF 和 epub 格式的文件。

总之,就是好用,好使,加好看。

刚好近日准备通过 GitBook 来写一些教程,这里就先简明介绍一下它的使用。嗯?我写的什么教程? 哈哈,就不告诉你,等写好了再说 <( ̄▽ ̄)> 哇哈哈…

安装

因为 GitBook 是一个基于 Node 开发的命令行工具。因此需要您自行配置 Nodenpm 环境。如果你已经安装好这些环境之后,GitBook 的安装只需要一步就能完成!

$ npm install -g gitbook-cli

使用

GitBook 的用法非常简单,老规矩,先看一下我们都有哪些命令可以使用:

$ gitbook help

  build [book] [output]      build a book
    --format     Format to build to (Default is website; Values are website, json, ebook)
    --log    Minimum log level to display (Default is info; Values are debug, info, warn, error, disabled)

  pdf [book] [output]    build a book to pdf
    --log    Minimum log level to display (Default is info; Values are debug, info, warn, error, disabled)

  epub [book] [output]   build a book to epub
    --log    Minimum log level to display (Default is info; Values are debug, info, warn, error, disabled)

  mobi [book] [output]   build a book to mobi
    --log    Minimum log level to display (Default is info; Values are debug, info, warn, error, disabled)

  serve [book]   Build then serve a gitbook from a directory
    --port   Port for server to listen on (Default is 4000)
    --lrport     Port for livereload server to listen on (Default is 35729)
    --watch      Enable/disable file watcher (Default is true)
    --format     Format to build to (Default is website; Values are website, json, ebook)
    --log    Minimum log level to display (Default is info; Values are debug, info, warn, error, disabled)

  install [book]     install plugins dependencies

  init [directory]   create files and folders based on contents of SUMMARY.md

实际上我们最常用的命令只有两个:

  • gitbook init: 初始化书籍目录
  • gitbook serve: 在编写书籍时启动一个服务器,自动编译&更新内容,并在浏览器中预览

使用

gitbook init

首先,通过终端(PC 下可使用命令提示符)进入到你想要书写内容的目录,然后执行 gitbook init 命令,之后目录中会自动生成 README.mdSUMMARY.md 两个文件。

这两个文件在 GitBook 项目中是必须存在的,其中 README.md 是对书籍的简单介绍,SUMMARY.md 是对书籍目录的描述,并且 GitBook 会通过该文件中的目录描述自动生成对应的目录和文件。

其中,SUMMARY.md 文件中内容的格式是这样的:

* [Chapter1](chapter1/README.md)
  * [Section1.1](chapter1/section1.1.md)
  * [Section1.2](chapter1/section1.2.md)
* [Chapter2](chapter2/README.md)

当你修改了 SUMMARY.md 文件中的内容后,你可以再次使用 gitbook init 来自动生成对应的目录和文件。

Multi-Languages

如果你要写的书籍是多语言版,你只需要创建一个 LANGS.md 文件,然后编写配置内容即可:

* [English](en/)
* [French](fr/)
* [Español](es/)

gitbook serve

书籍目录结构创建完成以后,我们就可以使用 gitbook serve 来编译和预览书籍了:

gitbook serve 命令实际上会首先调用 gitbook build 编译书籍,完成以后会打开一个 web 服务器,监听在本地的 4000 端口。

$ gitbook serve

Live reload server started on port: 35729
Press CTRL+C to quit ...

info: loading book configuration....OK
info: load plugin gitbook-plugin-highlight ....OK
info: load plugin gitbook-plugin-search ....OK
info: load plugin gitbook-plugin-sharing ....OK
info: load plugin gitbook-plugin-fontsettings ....OK
info: load plugin gitbook-plugin-livereload ....OK
info: >> 5 plugins loaded
info: start generation with website generator
info: clean website generator
info: OK
info: generation is finished

Starting server ...
Serving book on http://localhost:4000

之后,你就可以使用浏览器打开 http://127.0.0.1:4000 查看效果了。就是这么简单。

页面效果如下:

https://camo.githubusercontent.com/c1b6c55fca8e171120ce1fd73afcee699cc2a98f/68747470733a2f2f7261772e6769746875622e636f6d2f476974626f6f6b494f2f676974626f6f6b2f6d61737465722f707265766965772e706e67

你可以尽情的使用 Markdown 来编写文章了,完全不需要关心样式和排版呢。

GitBook 编辑器

如果你不喜欢使用命令行,这里也有 GitBook 可视化编辑器,https://www.gitbook.com/editor/

GitBook.com

GitBook.com 是一个围绕 GitBook 发行书籍的社区,于 2014 年初创,GitBook.com 提供免费和付费的服务,而且免费账户就可以享受诸多服务,包括:

  • 1 本私有书籍
  • 托管不限数量的公开书籍
  • 售卖不限数量的书籍,并分享 80% 的书籍收入
  • 不限数量的协作者
  • 免费的在线书籍编辑器

其他命令

  • gitbook build: 会生成相应的 HTML 文件供分发。
  • gitbook pdf: 生成 PDF 文件
  • gitbook epub: 生成 epub 文件
  • gitbook mobi: 生成 mobi 文件

高级技巧

个性化配置

我们通过配置 book.json 文件来修改 GitBook 在编译书籍时的行为,例如:修改书籍的名称,显示效果等等。

GitBook 在编译书籍的时候会读取书籍源码顶层目录中的 book.jsonbook.json 支持的具体配置请参考官方文档

安装插件

你可以通过 gitbook install 命令来安装一些诸如 disqusmultipart 这些实用的第三方插件。

不要害怕 Rebase

Git 的 rebase 命令是 Git 用户感到害怕和迷惑的一个常见原因,特别是那些来自可能更集中的版本控制系统的用户。这很正常。Rebase 是一个不可思议又充满魔力的怪兽,一上来不管三七二十一就改变历史。

Rebase 有点像指针。它是这样一个令人困惑的结构:每个人都在谈论它,但是你并不清楚为什么会有人使用它,然后突然一切都“啪嗒”一下,整个想法都变得显而易见和难以置信的简单。

在这篇文章中我会迫使你“啪嗒”一下,这样你就可以回到工作中并传播 git rebase 的神奇。

究竟什么是 Rebase?

Git Rebase 是一个很简单的工具,用来取出一些在某个地方创建的提交,并假装它们一直是在另一个地方创建的。

好的,我知道了。可是这意味着什么呢?

让我们来看一个例子。我们在这个仓库中有两个分支:masterfeature/foofeature/foo 是基于 master 分离出去的分支,并且在 feature/foo 分支上产生了一些提交。master 也发生了移动,就像世界不会因为少了你的关注而停滞不前。

这是目前的状态

我们想将一些更改从 master 整合进 feature/foo 中,但是我们不想每次执行这个整合时都处理一次令人讨厌的合并提交。

Rebase 就是一个让你有能力整合发生在源分支上的更改而不需要执行合并(merge)从而不会产生合并提交的工具。

这是 rebase 之后的情况。(fast-forward 版本)

DF 两个提交已经被重新放在master 的顶部,即当前指向的 G 提交。你可能会注意到这两个提交实际上已经被重命名为了 D`F`,并且提交的 SHA-1 值也不一样。这是为什么呢?

Git 中的提交不可变更

一个提交具有一些与之相关的属性:一个父提交、一个时间戳、提交时仓库的快照(提交不仅仅是变更集)。这些值是 Git 在计算标识一个提交的 SHA-1 时所用到的。

由于提交是不可变的,并且一个 SHA-1 应该唯一标识一个提交,因此 Git 需要创建一个新的提交来包含原始提交中相同的仓库快照,但是每个提交都有一个不同的父提交和时间戳

这导致新的提交看起来与原始提交相同,但是具有不同的 SHA-1。


找出提交

当我们从 feature/foo 分支上运行 git rebase master 时,Git 怎么知道哪些提交需要移动呢?

让我们先看看每个分支上的提交的文氏图(Venn diagram)。

从上图中我们可以看到每一个分支都有 ABC 这几个提交。master 分支还拥有 EG 提交但是 feature/foo 分支没有。feature/foo 拥有 FD 提交但是 master 分支没有。

Git 会做一个减法:{commits on feature/foo} — {commits on master},来找出正确的提交。这个结果就是 DF

我们能证明这一点吗?

当然,一个简单方式是使用 git log 来看我们从这组减法中得到的确切提交。

git log master..feature/foo 向我们展示 bc1f36b640e713 提交。

如果你在 .. 后省略了一个分支,那么会默认为是当前分支。

看起来不错。让我们来看看更广泛的视角以确保我不是在糊弄。

这些 SHA-1 看起来很熟悉。

这里并没有 76f5fd1 和 22033eb,因为我们是从 master 分支的 7559a0b 提交开始分离的。


如果我们现在执行一个 rebasemaster,我们会立即看到 76f5fd122033eb 出现在我们在 feature/foo 分支上创建出的提交的前面。

Git 正在像我们期望中的那样重新应用提交。

看起来熟悉吗?

我们之前见过这个了。

我们现在有一个很好的线性历史。你应该能够想到在此刻 fast-forward 的合并会如何发生。

rebase 策略还有一个已知的额外好处,就是如果你的 CI 管道(CI pipeline)在功能分支上通过了,那么在合并后的主分支上它也会通过。如果是一个非线性的合并策略,你就不能保证这一点。


使用强制手段

如果 feature/foo 分支已经被推送过(push),并且在 rebase 之后尝试进行另一个推送,Git 会很委婉地拒绝推送。这是为什么呢?

Git 会尽其所能来防止意外覆盖历史,这是一件好事。

我们来看一下 Git 所认为的 feature/foo 分支在远程仓库中是什么样的?

现在我们来看一下我们告诉 Git 要做的事情。

从 Git 的角度来看,提交 DF 即将丢弃。Git 会给你这样一行友好的信息:Updates were rejected because the tip of your current branch is behind

你或许会说,“但是我可以在你这个很棒的图片中清晰地看到,feature/foo 分支比之前更进一步了啊。” 这是一个很好的观察结果,但是 Git 只会看到远程仓库中的 feature/foo 包含 bc1f36b640e713,但是你本地的 feature/foo 不包含这些提交。因此为了不丢失这些提交,Git 会委婉地拒绝一个正常的 git push,并要求你执行 git push --force


如果你从这篇文章中带走一件东西,那么请记住,rebase 只是简单的查找出在某个分支上创建的提交,然后使用相同的内容但是新的父提交或基础提交(base commit)来创建新的提交。


如果你喜欢我的文章,请为我点赞。

关注 HackernoonJared Ready 来获取更多高质量的软件工程相关的内容吧。

本文根据 Jared Ready 的《Don’t Fear The Rebase》所译,整个译文带有自己的理解与**,如果译得不好或有不对之处还请同行朋友指点。如需转载此译文,需注明英文出处:https://hackernoon.com/dont-fear-the-rebase-bca683888dae

是时候来用 Slush 构建你自己的脚手架了

Slush 是什么?

简单的来说,Slush 就是一个脚手架生成工具。什么?脚手架?这是什么鬼?嗯,脚手架嘛,自然是这个样子咯~

什么?你问的是编程中的脚手架呀?啊,这么说吧。身为一个前端开发者,每次新建一个项目的时候是不是要创建好多个文件夹、配置文件?写个文档是不是要创建好多个目录?然而每个项目的结构和配置文件都大同小异,是不是早已繁琐感觉人生无望,失去了活着的意义?

就在这个时候,Slush 横空出世,能够让你轻松搞定这些繁琐的事情,重新找回人生的意义,你就说吼不吼啊。从此麻麻再也不用担心我整天都在忙着创建文件夹啦。

道理我都懂,可我大 Yeoman 用的好好的,为什么要换新?

嗯。Yeoman 确实也是一个很好用的脚手架工具,历史悠久。然而它以 Grunt 为基础工具,上手难度大大提高。在轮子层出不穷的前端领域早已是风前残烛。而 Slush 则是基于 Gulp 的 『流式』**作为基础工具,当你在做定制化脚手架时,Gulp 简单易用的特点则能让你轻轻松松搞定。

噢,这么屌?那该怎么用呢?

说了这么多,我到底该怎么用?

好啦,废话不多说啦,我们赶紧来趁着这个热乎劲看看怎么使用吧。

1. 安装 slush

首先,你得有 NodeJS 环境,什么?连 NodeJS 都没装?赶紧回家洗洗睡吧。如果你已经有了呢,你就可以通过 npm 直接将 slush 安装到全局环境下啦:

npm install -g slush

安装完了之后,你可以执行下面这行命令来确保安装成功:

slush -v

如果你能看到输出了一个版本号,就说明已经安装成功啦。下面我们就来看一下如何使用吧。

2. 安装第三方脚手架

在使用 slush 创建项目之前,你得先安装一些别人开发好的脚手架。安装好脚手架之后才能根据脚手架生成约定好的项目结构哟。

咦?不知道有什么脚手架?快来 大厅 里找找吧。

很好,你已经找到了自己喜欢的脚手架了,我们快来安装它吧。打住,提醒你一下,脚手架要安装到全局环境下才有效哟。

npm install -g slush-react-starter-kit

3. 开始生成项目吧

现在我们已经安装好需要的一切了,终于可以开始创建项目啦。

首先,创建一个项目文件夹并进入文件夹中:

mkdir my-first-slush-project
cd my-first-slush-project

其次,执行 slush 生成命令:

slush react-starter-kit

react-starter-kit 是什么鬼?我们安装的明明是 slush-react-starter-kit 呀。没错,在生成项目的时候,slush 后面跟的脚手架名字中是不带 slush 关键词的。就是这么任性。

没找到好使的,宝宝想要自定义怎么办?

当然了,可能你翻遍了整个大厅都没找到自己想要的,迫切想要自己定制一个脚手架怎么办呢?且听我慢慢道来。

其实很简单啦,Slush 脚手架就是一个普通的 npm package,唯一需要注意的有这么几点:

  1. 名字要以 slush-* 的方式
  2. package 中包含一个 slushfile.js 文件
  3. package.json 文件中加上 slushgenerator 关键词方便别人检索
  4. 模板文件放在 templates 文件夹中
  5. 别忘了安装 gulp 作为本地依赖啦

假设你已经按照上面这些约定做好了准备工作,那么接下来我们就可以搞一件大新闻啦。

第一步:创建模板文件

首先,你要将模板文件(就是运行脚手架之后生成的项目文件)全部放到 templates 文件夹中

第二步:在 slushfile.js 文件中编写任务流。

前面已经说到 Slush 是基于 Gulp 作为基础工具的,所以你只需要按照 Gulp 的使用方法在 slushfile.js 编写任务流就可以啦。

咦,好像有点不太对,既然是用 Gulp,那么 gulpfile.js 文件呢?

这里确实是不需要 gulpfile.js 文件啦,因为 Gulp 任务都在 slushfile.js 文件中写啦,Slush 会帮你自动驱动 Gulp 的啦。

好了,那么 slushfile.js 文件中的到底该怎么写呢?放着我来,小哥亲自给你示范一下:

var gulp = require('gulp'),
    install = require('gulp-install'),
    conflict = require('gulp-conflict'),
    template = require('gulp-template'),
    inquirer = require('inquirer');

gulp.task('default', function (done) {
  inquirer.prompt([
    {
    	type: 'input',
    	name: 'name', 
    	message: 'Give your app a name', 
    	default: gulp.args.join(' ') // 从运行参数中获取值作为 name 的默认值。
    },
    {
    	type: 'confirm',
    	name: 'moveon',
        message: 'Continue?'
    }
  ]).then(function (answers) {
    if (!answers.moveon) {
      return done();
    }
    
    gulp.src(__dirname + '/templates/**')      // 使用脚本所在的目录作为相对路径。
      .pipe(template(answers))                 // Lodash 模板支持,可以方便的在模板中进行插值。
      .pipe(conflict('./'))                    // 当文件冲突时,询问是否覆盖。
      .pipe(gulp.dest('./'))                   // 输出到执行命令的当前文件夹中。
      .pipe(install())                         // 使用 `bower install` 或 `npm install` 执行安装操作。
      .on('end', function () {
        done();                                // 告知完成。
      });
  });
});

PS: 去哪里发现诸如 [inquirer](https://github.com/SBoudrias/Inquirer.js) 这么好用的 package 呢?你可以关注下 github.com/sqrthree/awesome-npm-packages 哟。

现在就已经搞定啦,接下来怎么使用呢?因为 Slush 调用的是全局环境下的脚手架,但是目前我们的脚手架并不在全局环境中,然而你还没发布这个脚手架,不能直接工作 npm install -g 进行全局安装,所以显然是不!能!用!啦!哈!哈!哈!

别着急砸电脑嘛,我们还有一个办法捏。那就是通过 npm link 命令将当前脚手架挂载到全局环境中啦。你只需要在当前文件夹中执行 npm link,搞定,收工(前提是 package.json 已经写好)。然后就可以随便找个文件夹安装我们上面说的方法使用脚手架啦。

生成 Slush 脚手架的脚手架

尽管自定义一个脚手架已经非常方便了,但是细心的你会发现几乎每个脚手架之间 slushfile.js 也都大同小异,只是 templates 文件夹中的模板文件不一样,所以呢,你懂得😉。

slush-generator 就是这么一个让我们来生成 Slush 脚手架的脚手架。有了它,创建自定义脚手架的时候异常方便。

第一步:安装 slush-generator

npm install -g slush-generator

第二步:创建并进入自定义脚手架的文件夹

mkdir my-slush-generator
cd my-slush-generator

第三步:运行任务:

slush generator

之后会让你回答一些问题,在回答过之后,你的自定义脚手架目录就已经生成好啦。接下来只需要在 templates 文件夹中放置你需要的文件就好了。

查看已经安装好的脚手架

直接输入 slush 即可看到已经安装过的脚手架:

➜  slush
[slush] Installed generators
[slush] ├── generator (0.2.11)
[slush] └── koa2 (0.1.0)

怎么样?是不是已经迫不及待的想要尝试了?

喔,对了,少侠留步,差点忘了告诉你一件事情:

[译] 在 Chrome 开发者工具中调试 node.js

这篇文章介绍了一种在 Chrome 开发者工具里面开发、调试和分析 Node.js 应用程序的新方法。

devtool

最近我一直在开发一个命令行工具 devtool,它可以在 Chrome 的开发者工具中运行 Node.js 程序。

下面的记录显示了在一个 HTTP 服务器中设置断点的情况。

movie

该工具基于 Electron 将 Node.js 和 Chromium 的功能融合在了一起。它的目的在于为调试、分析和开发 Node.js 应用程序提供一个简单的界面。

你可以使用 npm 来安装它:

npm install -g devtool

REPL

在某种程度上,我们可以用它来作为 node shell 命令的替代品。例如,我们可以这样打开一个 REPL (译者注: REPL 全称为"Read-Eval-Print Loop",是一个简单的、交互式的编程环境)。

devtool

这将启动一个带有 Node.js 特性支持的 Chrome 开发者工具实例。

console

我们可以引用 Node 模块、本地 npm 模块和像 process.cwd() 这样的内置模块。也可以获取像 copy()table() 这样的 Chrome 开发者工具中的函数。

其他的例子就一目了然了:

# run a Node script
devtool app.js

# pipe in content to process.stdin
devtool < audio.mp3

# pipe in JavaScript to eval it
browserify index.js | devtool

开发

我们可以在通用模块和应用程序的开发中使用 devtool,来代替像 nodemon 这样目前已经存在的工具。

devtool app.js --watch

这行命令将会在 Chrome 开发者工具中的控制台中启动我们的 app.js, 通过 --watch 参数,我们保存的文件将(自动)重新载入到控制台。

console

点击 app.js:1 链接,程序将会在 Sources 标签中把我们带到与之相关的那一行。

line

Sources 标签中,你也可以敲击 Cmd/Ctrl + P 按键在所有依赖的模块中进行快速搜索。你甚至可以审查和调试内置模块,比如 Node.js 中的那些。你也可以使用左手边的面板来浏览模块。

Sources

调试

因为我们能够访问 Sources 标签,所以我们可以用它来调试我们的应用程序。你可以设置一个断点,然后重新加载调试器(Cmd/Ctrl + R),或者你也可以通过 --break 标记来设置一个初始断点。

devtool app.js --break

break

下面是一些对于那些学习 Chrome 开发者工具的人来说可能不是特别常用的功能:

提示 - 当调试器暂停时,你可以敲击 Escape 按键打开一个执行在当前作用域内的控制台。你可以修改一些变量然后继续执行。

Imgur

分析

devtool 的另一个功能是分析像 browserify, gulpbabel 这样的程序。

这里我们使用 console.profile() (Chrome 的一个功能)来分析一个打包工具的 CPU 使用情况。

var browserify = require('browserify');

// Start DevTools profiling...
console.profile('build');

// Bundle some browser application
browserify('client.js').bundle(function (err, src) {
  if (err) throw err;

  // Finish DevTools profiling...
  console.profileEnd('build');
});

现在我们在这个文件上运行 devtool :

devtool app.js

执行之后,我们可以在 Profiles 标签中看到结果。

profile

我们可以使用右边的链接来查看和调试执行频率较高的代码路径。

debug

高级选项

实验

Chrome 会不断的向他们的开发者工具中推送新功能和实验,例如 Promise Inspector。你可以通过点击右上角的三个点,然后选择 Settings -> Experiments 来开启他们。

experiments

一旦启用,你就可以通过敲击 Escape 按键来调出一个带有 Promises 监视器的面板。

提示: 在 Experiments 界面,如果你敲击 Shift 键 6 次,你会接触到一些甚至更多的实验性(不稳定)的功能。

--console

你可以重定向控制台输出到终端中(process.stdoutprocess.stderr)。也允许你通过使用管道将它导入到其他进程中,例如 TAP prettifiers。

devtool test.js --console | tap-spec

--process.argv

你的脚本可以像一个普通的 Node.js 应用那样解析 process.argv。如果你在 devtool 命令中传递一个句号(--),它后面的所有内容都会被当做一个新的 process.argv 。例如:

devtool script.js --console -- input.txt

现在,你的脚本看起来像这样:

var file = process.argv[2];
console.log('File: %s', file);

输出:

File: input.txt

--quit--headless

使用 --quit,当遇到了一个错误(如语法错误或者未捕获的异常)时,进程将会安静的退出,并返回结束码1

使用 --headless,开发工具将不会被打开。

这可以用于命令行脚本:

devtool render.js --quit --headless > result.png

--browser-field

一些模块为了更好的在浏览器中运行或许会提供一个入口点。当你需要这些模块时,你可以使用 --browser-field 来支持 package.json flag

例如,我们可以使用 xhr-request ,当带有 "browser" 字段被引用时,这个模块会使用 XHR。

const request = require('xhr-request');

request('https://api.github.com/users/mattdesl/repos', {
  json: true
}, (err, data) => {
  if (err) throw err;
  console.log(data);
});

在 shell 中执行:

npm install xhr-request --save
devtool app.js --browser-field

现在,我们可以在 Network 选项卡中审查请求:

requests

--no-node-timers

默认情况下,我们提供全局的 setTimeout and setInterval,因此他们表现的像 Node.js 一样(返回一个带有 unref() and ref() 函数的对象)。

但是,你可以禁用这个方法来改善对异步堆栈跟踪的支持。

devtool app.js --no-node-timers

async

V8 Flags

在当前目录,你可以创建一个 .devtoolrc 文件来进行诸如 V8 flags 这样的高级设置。

{
  "v8": {
    "flags": [
      "--harmony-destructuring"
    ]
  }
}

访问这里获取更多细节

陷阱

由于程序是在一个 Browser/Electron 环境中运行,而不是在一个真正的 Node.js 环境中。因此这里有一些陷阱你需要注意。

对比

目前已经存在了一些 Node.js 调试器,所以你或许想知道他们之间的区别在哪。

WebStorm 调试器

WebStorm 编辑器里面包含了一个非常强大的 Node.js 调试器。如果你已经使用 WebStorm 作为你的代码编辑器,那对你来说很棒。

但是,它缺少一些 Chrome 开发者工具中的功能,例如:

  • 一个丰富的互动的控制台
  • 异常时暂停
  • 异步堆栈跟踪
  • Promise 检查
  • 分析

但因为你和你的 WebStorm 工作空间集成,所以你可以在调试时修改和编辑你的文件。它也是运行在一个真正的 Node/V8 环境中,而不像 devtool 一样。因此对于大部分的 Node.js 应用程序来说它更稳健。

iron-node

一个同样基于 Electron 的调试器是iron-nodeiron-node 包含了一个内置的命令来重新编译原生插件,还有一个复杂的图形界面显示您的package.jsonREADME.md

devtool 更侧重于把命令行、Unix 风格的管道和重定向和 Electron/Browser 的 API 当作有趣的用例。

devtool 提供各种各样的功能来表现的更像 Node.js (例如 require.main, setTimeoutprocess.exit),并且覆盖了内部的 require 机制作为 source maps,还有改进过的错误处理、断点注入、以及 "browser" 字段的解决方案。

node-inspector

你或许也喜欢 node-inspector,一个使用远程调试而不是构建在 Electron 之上的工具。

这意味着你的代码将运行在一个真正的 Node 环境中,没有任何 window 或其他的 Browser/Electron API 来污染作用域并导致某些模块出现问题。对于大型 Node.js 应用(即本地插件)来说它有一个强有力的支持,并且在开发者工具实例中拥有更多的控制权(即可以注入断点和支持网络请求)。

然而,由于它重新实现了大量的调试技巧,因此对于开发来说感觉可能比最新版的 Chrome 开发者工具要慢、笨拙和脆弱。它经常会崩溃,往往导致 Node.js 开发人员很无奈。

devtool 的目的是让那些从 Chrome 开发者工具中转过来的人觉得比较亲切,而且也增加了像 Browser/Electron APIs 这样的功能。

前端代码风格检查套件 FECS

All code in any code-base should look like a single person typed it, no matter how many people contributed. — idiomatic.js
在任一个代码库中,不管是多少人协同开发,所有的代码都应该看起来像是一个人写的。- idiomatic.js

This means strictly enforcing these agreed upon guidelines at all times.

今天要讲的不是代码规范,关于代码规范网上已经有了非常好的实践和各大公司公开的实践指南,大家可自行查询。 例如: code-guide chinese.

然而,有了规范是一回事,执行起来又是一回事。今天要介绍的就是一款按照指定风格检测代码是否符合规范的工具,通过工具的自动检测,以确保每一行代码都符合规范。

FECS 是什么?

fecs 是以百度前端代码规范为目标的基于 Node.js 的前端代码风格检测工具,套件内包括了 htmlcs、csshint、lesslintjformatter 等工具。

因此,fecs 不仅能检查 HTML/CSS/LESS/JavaScript 代码的规范问题,而且还能修复代码的规范问题。

FECS 能干什么?

fecs check

首先,主要功能就是代码格式的检查,当然了呢,因为是最初是供于百度内部使用的工具,自然就是以 百度前端代码规范 为首要目标,好在该规范第一开源,第二还不错,因此可以直接使用。

当然了,如果你不喜欢其中的某些规则,FECS 也是支持配置文件设置规则的方式的,具体的在下文说明。

需要说明的是,FECS 目前只支持 HTML/CSS/LESS/JavaScript 四种文件和语法的检测。

Javascript

Javascript 方面 FECS 采用了 eslint 检测引擎,因此你在自定义规则的时候可以参考 esling 的文档进行相关配置。FECS 只是在 eslint 基础之上针对百度的代码规范作了新的规则实现或调整。详细内容见 FECS 自有规则

CSS/LESS/HTML

CSS 的 linter 是使用了内部优化过的 csshint。LESS 和 HTML 方面则分别使用了 lesslinthtmlcs

FECS 的安装及其使用

安装

安装 FECS 需要依赖 node npm 环境支持,执行以下命令即可安装:

$ [sudo] npm install fecs -g

使用

使用方式可使用以下命令查看:

$ fecs --help
$ fecs check --help
$ fecs format --help

具体的命令参数?哎呀,官方已经写的够详细的了,还是看官方文档吧: FECS 命令参数

自定义配置

FECS 支持通过配置文件的方式指定特定的规则。

配置文件的支持来自 manis,支持使用 .fecsrcpackage.json,但以第一个找到的为准。配置文件 .fecsrc 大体是这个样子的:

{
    "files": [],

    "eslint": {...},

    "csshint": {...},

    "htmlcs": {...},

    "csscomb": {...}
    ...
}

比如说他们的JavaScript编码规范 中关于换行中有这样一条 对于if...else...try...catch...finally 等语句,推荐使用在 } 号后添加一个换行的风格,使代码层次结构更清晰,阅读性更好,这一条我就很不喜欢嘛,那我可以这样配置:

{
    "eslint": {
        "rules": {
            "brace-style": [2, "1tbs", {}]
        }
    }
}

这样配置之后再进行检测,就能愉快的按照下面这种写法愉快的 coding 了。

if (condition) {
    // some statements;
} else {
    // some statements;
}

多工具支持

详情支持列表请参考官方文档 工具支持

嗯。文档依旧写的很完善,基本上已经没什么好补充的了。

在这里我有一个小提示,就是工具对 atom 编辑器的支持相对于对 sublime 的支持来说要优秀很多, 包括检测速度呀,错误提示呀,atom 都略称一筹,这取决于 atom 优秀的插件机制。并且我在 sublime下面使用的时候发现了一个 bug,就是错误提示会显示为特殊编码导致无法以中文显示。解决方案呢,在这里leeight/Baidu-FE-Code-Style#6,不过感觉略麻烦的样子。

Tips:

FECS 的错误报告默认为英文格式,由各 linter 直接提供。FECS 根据百度前端代码规范,作了一次影射转换,通过指定 reporter 为 baidu 可以看到中文的报告输出效果,对于某些比较抽象的描述,会同时在括号内提供英文原文补充说明。

例如,你可以这样用:

fecs check --reporter=baidu 

或者,更直接一点,直接添加一个 alias,使其在执行 fecs check 命令时默认为中文输出。

alias fecs='fecs --reporter=baidu'

相关链接:

[译] JavaScript 开发者年度调查报告

截至目前有超过了 5000 人参与了(该次调查),准确的说是 5350 人。我迫不及待的想要和大家分享一下这次调查的细节。在分享之前我想要感谢参与调查的每一个人。这是 JavaScript 社区一个伟大的时刻,我对未来的事情感到无比激动。

我没有想到大家如此积极,下一次我一定会对版式做一些改进。换句话说,就是我会先将问卷调查放到 Github 上,以便于在开始调查之前,社区有一到两周的时间来收集改进问题和选项。这样,我就可以得到更精确的结果,也可以避免出现诸如 "我很震惊你竟然没有包含 Emacs" 这样的抱怨。

现在,基于调查结果。我将保持中立的态度发表一下调查结果,这样你就可以得出自己的公正的结论。

你写什么类型的 JavaScript?

有高达 97.4% 的受访者用 JavaScript 写 web 浏览器程序,其中有 37% 的受访者写移动端 web 程序。超过 3000 人(56.6%) 也写服务端的 JavaScript。在这些参与调查者的人中间,有 5.5% 的人还在一些嵌入式环境中使用 JavaScript,例如 Tessel 或 a Raspberry Pi (树莓派)。

少数参与者表示他们也在其他一些地方使用 JavaScript,尤其是在开发 CLI 和桌面应用方面。还有少数提到了 Pebble 和 Apple TV. 这些都归类在 Other(其他) 一类中,占总票数的 2.2%。

An screenshot of the percentages for the first question

你在哪里使用 JavaScript?

不出所料地,有 94.9% 的参与者在工作中使用 JavaScript,但是,统计中也有很大一部分(占总票数的 82.3%) 参与者也在其他项目中使用。其他的回复则包括了教学,好玩,和非盈利目的的使用。

An screenshot of the percentages for the second question

你写 JavaScript 多长时间了?

超过 33% 的受访者表示他们写 JavaScript 代码已经超过了 6 年时间。除了这些人之外,有 5.2% 的人一年前开始写 JavaScript 代码,12.4% 的人是两年前,还有 15.1% 的人是三年前。这说明在 5350 个投票者中,有 32.7% 的人是在近几年才开始写 JavaScript 的。

An screenshot of the percentages for the third question

如果可以的话,你使用哪种 compile-to-JavaScript(编译为 JavaScript 的) 语言?

有高达 85% 的受访者表示他们使用 ES6 编译成 ES5。与此同时,有 15% 的人仍然使用 CoffeeScript,15.2% 的人使用 TypeScript,只有区区 1.1% 的人使用 Dart

这是我想进一步探讨的问题之一,因为有 13.8% 的人选择了 “Other(其他)”,选择 “Othe(其他)” 的绝大部分的回答是 ClojureScript, elm, Flow, 和 JSX

An screenshot of the percentages for the fourth question

你更喜欢哪一种 JavaScript 编程风格?

回答这个问题的绝大多数开发者(79.9%)都选择了分号。相反,有 11% 的开发者指出更喜欢不使用分号。

逗号方面,44.9% 的开发者喜欢将逗号放在表达式的末尾,然而有 4.9% 的开发者喜欢先写逗号。

缩进方面,65.5% 的开发者更喜欢使用空格,然而有 29.1% 的开发者则更喜欢使用制表符(Tab)。

An screenshot of the percentages for the fifth question

你使用过 ES5 的哪些特性?

79.2% 的受访者都使用过 Array(数组) 的一些实用的方法,76.3% 的开发者使用严格模式。30% 的开发者使用 Object.create,而使用过 getters 和 setters 的开发者仅占了 28%.

An screenshot of the percentages for the sixth question

你使用过 ES6 的哪些特性?

显然,在这些投票中,箭头函数是使用最多的 ES6 特性,占了 79.6%。在所有调查者中,Let 和 const 加在一起一共占了 77.8% 。promises 也有 74.4% 的开发者采用。不出所料,只有 4% 的参与者使用 proxies,只有 13.1% 的用户表示他们使用 symbols,同时有超过 30% 的人说他们使用 iterators。

An screenshot of the percentages for the seventh question

你写测试么?

有 21.7% 的开发者表示他们从不写任何测试。大部分人偶尔写一些测试。34.8% 的人总是写测试。

An screenshot of the percentages for the eighth question

你运行持续集成测试吗?

和 CI 类似,尽管许多人(超过40%)不使用 CI 服务器,但是差不多有 60% 的人表示在少数时间会使用 CI,其中有 32% 的人总是在 CI 服务器上运行测试代码。

An screenshot of the percentages for the ninth question

你怎么运行测试代码?

59% 的开发者喜欢使用 PhantomJS 或是类似的工具来运行自动化浏览器测试。也有 51.3% 的开发者喜欢在 web 浏览器上手动运行测试。有 53.5% 的投票者会在服务器端进行自动化测试。

An screenshot of the percentages for the tenth question

你使用过哪个单元测试库?

似乎大部分投票者都使用 Mocha 或是 Jasmine 来运行他们的 JavaScript 测试用例。而 Tape 收到了 9.8% 的选票。

An screenshot of the percentages for the eleventh question

你使用过哪个代码质量检测工具?

看起来受访者在 ESLint 和 JSHint 之间分成了两派,但是 JSLint 还是有差不多 30% 的投票率,在这么多年之后势头还是惊人的强劲。

An screenshot of the percentages for the 12th question

你通过哪种方式来处理客户端依赖关系?

npm 接管了客户端依赖管理系统的天下,有超过 60% 的投票就是证明它的方式。Bower 仍然有 20% 的观众,而通过下载和插入 <script> 标签来管理的普通旧式方法则获得了 13.7% 的选票。

An screenshot of the percentages for the 13th question

你首选的脚本构建方案是什么?

构建工具的选择很分散,部分原因是有太多的不同的选项可供选择。Gulp 最流行,有着超过 40% 的选票,紧接着的是使用 npm run,有 27.8%。Grunt 得到了 18.5% 的支持者。

An screenshot of the percentages for the 14th question

你首选的 JavaScript 模块加载工具是什么?

目前,看起来大部分开发者都在 Browserify 和 Webpack 之间徘徊,而后者高出了 7 个百分点。29% 的用户表示他们在使用前面提到的这两个工具打包他们的模块之前会先使用 Babel 进行转换。

An screenshot of the percentages for the 15th question

你使用过哪些库?

现在回顾起来,这是一个受益于协同编辑的问题之一。jQuery 获得了超过 50% 的选票证明了它的势头依然很强劲。在参与投票的 JavaScript 使用者中,Lodash 与 Underscore 也被很大一部分开发者使用。 xhr 微型库只获得了 8% 的票数。

An screenshot of the percentages for the 16th question

你使用过哪些框架?

毫无意外地,React 和 Angular 遥遥领先于其他框架,有着 22.8% 的 Backbone 仍然处在一个安全的位置。

An screenshot of the percentages for the 17th question

你使用 ES6 吗?

受访者在这个问题上的反应相当分歧,有近 20% 的人几乎从不使用 ES6,超过 10% 的人只写 ES6,接近 30% 的人广泛使用 ES6,近 40% 的人偶尔使用。

An screenshot of the percentages for the 18th question

你知道在即将到来的 ES2016 中会有什么特性吗?

粗略地说,有超过一半的投票者表示不知道即将到来的 ES2016 中会有什么特性。另一半则对接下来的版本有所了解。

An screenshot of the percentages for the 19th question

你了解 ES6 吗?

超过 60% 的受访者似乎了解基本的概念。10% 的人对 ES6 毫不了解,有 25% 的受访者认为他们非常了解 ES6。

An screenshot of the percentages for the 20th question

你认为 ES6 是一个进步吗?

超过 95% 的受访者认为 ES6 是对于 JavaScript 语言来说是一个进步,下一次碰到 TC39 的会员我得祝贺他们。

An screenshot of the percentages for the 21th question

你更喜欢什么文本编辑器?

再一次,由于存在各种各样的选择导致结果非常分散。超过一半的受访者喜欢 Sublime Text,超过 30% 的受访者喜欢使用 atom 和 它的开源克隆版。超过 25% 的选票投给了 WebStorm,也有 25% 的选票投给了 vi/vim。

An screenshot of the percentages for the 22th question

你更喜欢使用什么操作系统作为开发环境?

超过 60% 的投票者使用 Mac,使用 Linux 和 Windows 的用户都接近 20%。

An screenshot of the percentages for the 23th question

你是通过哪种方式搜索到可重用的代码、库和工具的?

受访者似乎更青睐于 GitHub 和搜索引擎,但是也有一部分人使用博客,Twitter 和 npm 网站。

An screenshot of the percentages for the 24th question

你参加过 JavaScript 的社交活动吗?

有近 60% 的人参加过至少一次,74% 的人表示他们喜欢参加聚会。

An screenshot of the percentages for the 25th question

在你的 JavaScript 应用中,你都支持哪些浏览器?

回答相当分散,但是好在大多数受访者表示他们不再处理使用 IE6 的客户(的问题)了。

An screenshot of the percentages for the 26th question

你会定期了解有关 JavaScript 的最新特性吗?

有 80% 的受访者会尝试实时了解并持续学习 JavaScript 的最新特性。

An screenshot of the percentages for the 27th question

你在哪了解最新的 JavaScript 特性?

不出所料地,Mozilla 开发者网络 在 JavaScript 文档和新闻方面处于领先地位。JavaScript 周刊 也是一个非常受欢迎的新闻和文章的直接来源,它有着超过 40% 的投票。

An screenshot of the percentages for the 28th question

你听说过下面哪些新特性?

超过 85% 的人听说过 ServiceWorker,我很想知道这些人中有多少人使用过它。

An screenshot of the percentages for the 29th question

除了 JavaScript,你还主要使用哪些语言?

这有太多的语言可供选择,我肯定会漏掉一些。但是结果不言自明。

An screenshot of the percentages for the 30th question

谢谢

最后,我想感谢参与此次调查的每一个人。这次调查的受欢迎程度超出了我的预期,我很期待明年再进行一次类似的调查。我希望,那将会是一个更多样性的,也许会再少一点倾向性的调查。

你从这次调查中获得了什么呢?

[译] jQuery 3.0 —— 下一代的 jQuery

2014年10月29日,jQuery 官方博客上更新了一篇博文,描述了关于下一代 jQuery 的一些信息。实际上这篇博文至今都已经一年时间了,jQuery 官方团队也早在2015年7月13日发布了 jQuery 3.0.0-alpha1 版本。我之前也只是匆匆的看过一遍,今日闲着无事,就尝试翻译了一下并发布了这篇迟到了一年的译版,想要了解 3.0 中的新特性的话可以关注我后续的更新。

正文开始

很难相信从 jQuery 发布以来已经过去八年了,过去的这些年 Web 开发已经改变了很多, jQuery 也随之变化着。在这个过程中,团队一直在保持对旧代码的兼容性和支持目前最好的 Web 开发实践之间努力平衡着。

其中最好的做法就是语义化版本,或者简单的称之为 semver,从实践的角度看,semver 给了开发者(以及构建工具) 一个避免由于切换软件版本导致的风险的方法。版本号为 MAJOR.MINOR.PATCH 的格式,并且其三个组成部分均为整数。在semver 中,如果 MAJOR 改变了,就意味着在 API 中出现了不兼容的改变,因此开发者们需要当心。

jQuery 中版本控制变得更加微妙,(对 jQuery 来说) 浏览器的兼容性和 API 的兼容性同等重要。为了创造一个 “苗条” 的 jQuery ,团队在2013年开始放出了两个版本。第一个版本保持着 1.x 的编号,当前(截止到原文发布时)最新版本为 1.11.1,其保持了最大数量的浏览器兼容性。第二个版本从 2.0.0 开始,目前是 2.1.1,为了精简代码,放弃了对 IE8及其以下版本浏览器的支持。1.x 和 2.x 版本的 jQuery 都有着相同的公开 API,尽管他们在内部实现上有一些不同。

我们的下一个版本将会使用一种全新的命名方式。像之前一样,仍然会有两个不同的发布文件。现在的 1.11.1 版本的继任者将被称之为 jQuery Compat 3.0jQuery 2.1.1 则将由 jQuery 3.0来接替。在 npmBower 上(译者注: 这是目前非常流行的前端包管理工具),它们会是两个不同的包,但它们会共享同一个版本号,来说明它们在API层面上的行为是一致的。

这次版本发布之后,我们也将调整对浏览器的支持策略。主 jQuery 包将继续保持短小精悍,并且只支持在发布之时广泛使用的常青浏览器(evergreen browsers 指的是特定浏览器的当前和此前的若干版本)。我们也会根据市场份额在这个包的基础上支持更多的浏览器。而 jQuery Compat 包则提供更广泛的浏览器支持,但是付出的代价就是文件变得很大,执行效率也会低一些。

尽管这一次版本号跳跃很大,但是对于大多数 jQuery 代码来说,我们不期望造成很多的代码迁移问题。我们在这次版本升级中可是符合 semver 中的好公民的标准的。诸如像移除已废弃的方法这样的改变会被新版本的 jQuery Migrate 插件检测出来,这样一来,发现并且修复他们就变得容易多了。我们也会在将来的博客文章中讨论这些变化中的更多细节。

下面就是一些 jQuery API 3.0 版本要说的内容:

  • 如果你需要支持更多更广泛的浏览器,包括诸如 IE8, Opera 12, Safari 5 等,请使用 jQuery-Compat 3.0.0 版本。我们建议大多数网站都使用这一版本,因为它为网站的来访者提供了最好的兼容性支持。
  • 如果你的网站仅仅是为了那些最先进的浏览器而建,或者仅仅是一个基于 HTML 的应用以嵌入一个 web 视图(例如: PhoneGap,Cordova),你预先知道其使用的是哪一个浏览器解析引擎, 那就使用 jQuery 3.0.0 吧。
  • 除非我们宣布,否则对应的主、次版本号相同的两个包都会有相同的公开 API。这样开发者就能够很容易的在两个包之间切换,并且在第三方 jQuery 插件中拥有最好的兼容性。

未来每一个版本发布的时候,我们都会同时放到 npmbower 上。两个包也会以单个文件的形式在 jQuery CDN 上提供。在那里使用他们和根据你自己的需要去包含 jquery-compat-3.0.0.jsjquery-3.0.0.js 一样简便。我们也和 Google’s CDN 的运营人员谈过,他们也会为这两个包提供支持。

随着我们在3.0版本方面工作的推进,我们会向所有人告知代码变更、浏览器支持等一切细节的更新。敬请期待吧!

本文根据 Dave Methvin 的《jQuery 3.0: The Next Generations》所译,整个译文带有自己的理解与**,如果译得不好或有不对之处还请同行朋友指点。如需转载此译文,需注明英文出处:http://blog.jquery.com/2014/10/29/jquery-3-0-the-next-generations/

相关链接

聊一聊 JS 中的『隐式类型转换』

类型转换还不行?还非得隐式?这是什么高级玩意?

废话不多说,我们先上一盘🌰,额,不对,先看一个例子吧。

3 + true

实际上在大多数编程语言中,都会认为上面这个表达式是错误的。因为布尔表达式与算术运算是不兼容的。尤其是在静态语言中,甚至不会被运行运行。即使是动态语言中,通常虽然可以让程序运行,但是会抛出一个异常。

然而,然而, Javascript 不仅运行程序能够正常运行,而且还会顺利地产生结果 4。Javascript 真的是对类型错误出奇的宽容啊。看起来很像是一件好事对不对?

基本上,在 Javascript 中,只有在一些极少数情况下才会因为类型错误而抛出一个异常。诸如: 调用非函数对象或者获取 null / undefined 的属性时。

但是在大多数情况下,Javascript 都是不会抛出异常的。这个『小婊砸』反而按照多种多样的转换协议偷偷的强制转换为她期望的值。诺,你看,还花样转换呢,真会玩嘛。这就是所谓的『隐式类型转换』。

那么,上面那个例子中,究竟是发生了什么样的转换方式呢?

首先,Javascript 这个『小婊砸』在遇到算数运算符(-*/%)的时候会在运算之前将参与运算的双方转换成数字。

那么问题又来了,true 怎么就转换成数字了呢?实际上我们通过 Number(true) 就可以看到, true 转换为数字之后就是为 1,相反,false 转换为数字之后就对应为 0。

细心的你可能发现我在上面并没有提到 + 运算符,那是因为它更复杂。因为它既承担着数字相加,又肩负着字符串连接操作的重任。具体的行为取决于参数的类型。

但是,如果一个数字和一个字符串相加,会碰撞出什么样的火花呢?

显然 Javascript 这个『小婊砸』更偏爱字符串多一点,她会将数字(toString())转换为字符串,然后执行字符串连接操作。

例如:

"1" + 2;    // "12"
1 + "2";    // "12"

但是,注意,Javascript 对操作顺序非常敏感,以至于会发生这样的事情:

1 + 2 + "3";    // "33"

因为加法运算是自左向右的,因此它等同于下面的表达式:

(1 + 2) + "3";    // "33"

再来看这一个例子:

if (1 == true) {
    alert("true");
} else {
    alert("false");
}   

相信你一定轻松的猜到了结果对不对?

但是,哼,你以为我的问题会这么简单么?那岂不是太小看你了。

我们都知道,Javascript 中,数字 0 为假,非0 均为真, 那么我想问的是,在上面的条件语句中,到底是 1 被隐式类型转换了呢还是 true 被隐式类型转换了呢?

实际上在条件判断运算 == 中的转换规则是这样的:

  1. 如果比较的两者中有布尔值(Boolean),会把 Boolean 先转换为对应的 Number,即 0 和 1,然后进行比较。
  2. 如果比较的双方中有一方为 Number,一方为 String时,会把 String 通过 Number() 方法转换为数字,然后进行比较。
  3. 如果比较的双方中有一方为 Boolean,一方为 String时,则会先将双方转换为数字,然后进行比较。
  4. 如果比较的双方中有一方为 Number,一方为Object时,则会调用 valueOf 方法将Object转换为数字,然后进行比较。

例如:

1 == { valueOf: function() {return 1;} }    // true
1 + { valueOf: function() {return 1;} }    // 2

需要强调的是,在 Javascript 中,只有 空字符串数字0falsenullundefinedNaN 这 6 个值为假之外,其他所有的值均为真值。

说到 NaN,就不得不提一下 isNaN() 方法,isNaN() 方法自带隐式类型转换,该方法在测试其参数之前,会先调用 Number() 方法将其转换为数字。所以 isNaN('1') 这个语句中明明用一个字符串去测试,返回值仍然为 false 也就不足为怪了。

+ 号运算中还有一种更复杂的情况,那就是数字/字符串和对象进行运算的时候,上面已经举例说明了数字和对象运算的情况,我们再来说一下字符串和对象运算的情况。

当字符串和对象进行 + 运算的时候,Javascript 会通过对象的 toString() 方法将其自身转换为字符串,然后进行连接操作。

"1" + { toString: function() {return 1;} }    // "11"

之所以说它特殊,是因为当一个对象同时包含 toString()valueOf() 方法的时候,运算符 + 应该调用哪个方法并不明显(做字符串连接还是加法应该根据其参数类型,但是由于隐式类型转换的存在,类型并不显而易见。),Javascript 会盲目的选择 valueOf() 方法而不是 toString() 来解决这个问题。这就意味着如果你打算对一个对象做字符串连接的操作,但结果却是......

var obj = {
    toString: function() { return "Object CustomObj"; },
    valueOf: function() { return 1; }
};

console.log("Object: " + obj);    // "Object: 1"

隐式类型转换会给我们造成很多麻烦,那么该怎么避免呢?

建议在所有使用条件判断的时候都使用全等运算符 === 来进行条件判断。全等运算符会先进行数据类型判断,并且不会发生隐式类型转换。

[译] jQuery 3.0 以及兼容版的 Alpha 版本发布

从我们做出上一个重大的版本发布已经过去很长时间了,所以你理应再得到一个新版本。因此我们非常高兴的宣布 jQuery 3.0 的第一个 alpha 版本的发布。

尽管版本号已经到了 3.0,但是在升级目前已经存在的代码时,可以预期这些发布不会造成太多的麻烦。确实,只是一些用来调整重要版本冲突的零碎改变,但是我们希望这些改变不会实际影响到很多人。jQuery Migrate 插件可以很好的帮助你在你的代码中识别出兼容性问题。在这个 alpha 版本中,你针对于这些变化的反馈将会极大的帮助我们,所以请在你目前已有的代码和插件中尝试一下。

实际上,这里有两个版本。第一个版本是 jQuery 3.0, 这个版本支持现代浏览器和 IE9 以后的浏览器环境。第二个版本是 jQuery Compat 3.0,这个支持 IE8。作为一个额外的福利,就是 jQueryjQuery Compat 这两个版本都支持 Yandex 浏览器(一个2012年发布的免费软件)。你可以从 jQuery CDN 或者直接通过下面这些链接获取这两个文件。

https://code.jquery.com/jquery-3.0.0-alpha1.js

https://code.jquery.com/jquery-compat-3.0.0-alpha1.js

你也可以从 npm 中获取 alpha 版:

npm install [email protected]

npm install [email protected]

Major changes (主要的变化)

下面的这些内容只是高亮了这个版本中一些重要的新特性,代码的改进,还有一些 bug 的修复。在这篇文章下面和我们的 GitHub issue tracker 板块你可以看到一个完整的改变清单。在 Github 上,你还可以看到我们期待在下个 beta 版本和暂时还没发布的最终版中添加的新特性。

Simplified .show() and .hide() methods: 简化的 show 和 hide 方法

每个人的心中都认为 jQuery 中的 .hide() 方法就是把元素设置为 display:none,相反的,.show() 方法就是清除 display 因此元素会重新显示(假设父级元素没有被隐藏)。很简单,对么?

不,这么多年来,实际上有很多复杂特殊的例子,人们要求我们去修正一下,这些例子使得这些方法陷入一个复杂的原理集合之中。例如,如果一个元素在样式表中设置为 display: none 将会怎样?jQuery 会试着在元素上强制设置 display: block 去覆盖它。这是可以的。但是像 <li> 这样的一个正常的块元素通过不同的样式规则被设置为 display: inline 会怎么样呢?在一个元素被添加到 document 之前你调用了这个方法并且我们不知道这个元素拥有的 display 值的话又会怎样?确定这些事情需要花费额外的工作。有时仅仅是一个最后被证明是错误的猜想。

这些方法在元素上添加一个样式属性之后,在像是响应式设计中(元素的可见性需要通过媒体查询来设置)这样的技术上往往不能很好的表现。这个导致需要 jQuery 处理器去监听 orientationchangeresize 事件人工隐藏或显示部分页面;jQuery 打败了媒体查询正尝试实现的优雅的解决方案。

你可以看到 jQuery 已经完成了疯狂旅途中的一半路程了,但是完成整个旅程是行不通的。这个特殊的情况以及检查不仅复杂且难以完成,而且在大的页面中会造成具有重大意义的性能问题。

因此,代替的是,我们实验性的反抗这些方法的演变,重新回归到一个简洁的,原始的模型。这将会分解一些代码。如果一个元素在样式表中被设置为 display: none.show() 方法将不会再覆盖它。因此,转移到 jQuery 3.0 中有一个最重要的规则就是: 不要使用样式去设置 display: none 作为默认值,然后使用 .show() 或者其他方法来显示元素,例如使用 .slideDown().fadeIn() 方法来使它可见。

如果你需要让一个元素默认是隐藏状态,最好的方法是给元素添加一个像 hidden 这样的类名,然后在样式中去定义这个类为 display: none,然后你可以使用 jQuery.addClass().removeClass() 方法来添加或删除这个类来控制其可见性。另外一种方法是,你可以在元素显示到页面中之前,使用 .ready() 处理器并在其中调用 .hide() 方法。或者,如果你一定要在样式中保留默认值,你可以使用 .css("display", "block") (或其他合适的值)去覆盖样式。

我们知道这可能是 jQuery 3.0 中最受争议和最困难的改变,所以我们想把它放到这个早期版本中观察一下所造成的影响。请让我们知道这些改变如何影响了你的代码,以及你为了使用这个新版本所作出的改变。

jquery/jquery#1767
jquery/jquery#2057
jquery/jquery#2308

Special case with .data() names: 含有.data()名字的特殊事例

jquery/jquery#1751

我们也更新了我们的 .data() 方法来更有效的匹配 HTML5 dataset specification. 所有的键值现在都从 kebab-case 转换成驼峰命名法,不再理会访问方式,数字也不再参与转换。例如: 我们不再区分 foo-barfooBar,但是仍然区分 foo-42foo42。当通过调用无参数的 .data() 来取得所有的数据方法,或者尝试通过转换的键名(.data(“foo42”))而不是原始的(.data(“foo-42”))来获取数据时,这些改变将会发挥主要作用。

jQuery.Deferred is now Promises/A+ compatible: jQuery.Deferred现在兼容Promises/A+

jQuery.Deferred 对象为了兼容 Promises/A+ES2015 Promises 已经做出了更新,Promises/A+ Compliance Test Suite 检验。这意味着 引入一个 .catch() 方法,.then()方法也有一些重要的改变。

  • .then() 方法的回调函数中抛出的异常现在变成了一个可注入的值。以前,异常会一直往上冒泡,直至终止回调函数的执行,然后不可撤销的锁定 parent and child Deferred 对象。
  • 通过 .then() 方法创建的 Deferred 对象的 resolution 状态现在被它的回调函数控制——异常成为了注入值,并且 non-thenable 返回的结果成为了 fulfillment 值。以前,从注入处理器返回变成了注入值。
  • 回调函数总是被异步调用。以前,它们根据绑定或是 resolution 被立即调用,无论哪个更晚一些。
  • Progress 回调函数不再解决受约束的 Deferred 对象。

考虑一下下面的代码,哪个parent Deferred 被注入以及 child 回调函数产生异常:

var parent = jQuery.Deferred();
var child = parent.then( null, function() {
  return "bar";
});
var callback = function( state ) {
  return function( value ) {
    console.log( state, value );
    throw new Error( "baz" );
  };
};
var grandchildren = [
  child.then( callback( "fulfilled" ), callback( "rejected" ) ),
  child.then( callback( "fulfilled" ), callback( "rejected" ) )
];
parent.reject( "foo" );
console.log( "parent resolved" );

在 jQuery 3.0 中,在调用任何回调之前会先记录 “parent resolved”,每一个子回调将会记录 “fulfilled bar”, 然后 grandchildren 将会和错误 “baz” 一起注入。在之前的版本中,会记录一次 “rejected bar” (child Deferred 已经注入而不是fulfilled)然后通过未捕获到的错误 “baz” 中断(“parent resolved” 不会被记录并且 grandchildren 会保持 unresolved 状态)。

当捕获异常时有利于在浏览器中进行 debug, 使用注入回调来处理异常非常具有描述性(即显式的)。记住这个地方,你有责任在使用 promises 时总是添加至少一个注入回调,否则,任何错误都不会提示。

Legacy 行为可以通过使用现在还不宜用的 .pipe() 方法替换 .then() 方法来重新获取,

jQuery.when 方法也为了接受任何 thenable 对象而更新了,包括了原生的Promise对象。

jquery/jquery#1722
jquery/jquery#2102

移除了jQuery.ajax中Deferred方法的一些特殊情况

jqXHR 对象是一个Promise,但是也有像 .abort() 这样的额外的方法。因此你可以在创建之后停止一个请求。

随着用户越来越拥护类似像 AJAX 这样异步执行的 Promise 模式,通过 jQuery.ajax 进行 Promise 返回特殊事例的想法是越来越坏的主意。

success, error, complete
done, fail, always

注意,这些对于相同名字的回调函数没有任何影响,它们将会继续存在,而且不会被弃用。这个只会影响Promise 方法!

jquery/jquery#2084

错误事例不会默默地失败

也许在一个重要的时刻你会想知道,“窗口的偏移量是多少?” 然后你可能会意识到这是一个疯狂的问题 - 窗口怎么会有偏移量?

在过去,jQuery 有时会尝试去创建类似返回一些东西的事例而不是抛出一个错误。在这个询问窗口的偏移量的特殊事例中,到目前为止答案已经变成了 { top: 0, left: 0 },在 jQuery 3.0alpha 版本中,我们正在尝试抛出一个错误来让这些疯狂的请求不至于被默默地忽略掉这样的想法。请尝试使用 alpha 版本看一下是否存在一些依赖 jQuery 的代码出现无效输入的问题。

jquery/jquery#1784

.width(), .height(), .css(“width”), 和 .css(“height”) 方法将返回带有小数点的数值(不论何时浏览器都会这样做)。

以前,当你获取 width 和 height 的时候 jQuery 会对其进行取整。有一些浏览器会返回亚像素值 - 例如 IE 和 Firefox,并且有时当布局依赖这些值时用户需要这种精确度的值。我们不希望这些改变会对你的代码产生很大的影响,但是如果确实影响到了,请让我们知道。

jquery/jquery#1724

移除不赞成使用的事件别名

.load, .unload, 和 .error, 这些方法自从 jQuery 1.8 就已经弃用,而且永不使用。使用 .on() 注册监听器

jquery/jquery#2286

jQuery.swap, jQuery.buildFragment, 和 jQuery.domManip 不再从 jQuery 对象上获取。

这些方法常常仅在内部使用,而且也从来没有文档说明。为了避免疑惑,我们最终决定将他们私有化。

jquery/jquery#2224
jquery/jquery#2225

动画现在使用 requestAnimationFrame

除了 IE8IE9 之外,越来越多的平台都支持 requestAnimationFrame API,jQuery 现在在执行动画的时候也使用了此 API。这样的结果是会让动画越来平滑流畅,并且使用更少的 CPU 时间,在移动设备上也尽可能好的保存电量。

jQuery 尝试使用 requestAnimationFrame 了一些年头,但是在目前的代码中有一些很严重的兼容性问题,因此我们又把它撤销回去了。我们认为我们通过当浏览器标签页移出视野时暂停动画这种方式已经解决了这些问题中的大多数。然而,在真实的运行时环境中,任何依赖于动画的代码一直运行是一个不切实际的假想。

.unwrap( selector )

jQuery 3.0 之前,.unwrap() 方法不接收任何参数。selector 参数提供了一个确定哪个包装器该被移出的方式。

jquery/jquery#1744

Massive speedups for some jQuery custom selectors

感谢来自 Google 的 Paul Irish 所做出的一些排查工作,我们才可以识别出我们可以跳过的一些额外工作,像是 :visible 这样的常规的选择器在一个文档中使用好多次。特定的事例中现在在性能上能比以前快 17 倍。

记住,即使这些事情改善了,像是 :visible:hidden 这样的选择器也是很昂贵的,因为它们依赖于浏览器来决定什么时候元素确实显示在页面上。可能需要的是,在最差的情况中,CSS 样式和页面布局需要完整的重绘。尽管在大多数情况下我们不阻止使用他们,但是我们推荐你在你的页面上测试一下来确定这些选择器是否会造成一些性能问题。

jquery/jquery#2042

译者注:

具体的更新内容列表没有在此翻译,如果想具体了解请自行查看英文原文。

本文根据 Timmy Willison 的《jQuery 3.0 and jQuery Compat 3.0 Alpha Versions Released》所译,整个译文带有自己的理解与**,如果译得不好或有不对之处还请同行朋友指点。如需转载此译文,需注明英文出处:http://blog.jquery.com/2015/07/13/jquery-3-0-and-jquery-compat-3-0-alpha-versions-released/

相关链接

作为一个开源软件的作者是一种什么样的感受?

你的门外有几百人在排队。他们耐心地等待着你回答他们的问题、抱怨、pull requests 和 功能请求。

你想帮助他们,但是现在你要关闭它们。或许你已经辛苦工作了一整天,或者你累了,或者你只是想和你的家人、朋友享受一个周末。

但是如果你访问 github.com/notifications,它会持续地提醒你有多少人正在等着你:

screenshot showing 403 unread GitHub notifications

当你设法找到一些空闲时间后,你打开门并接待了第一个人。他们非常善意。他们尝试使用你的项目,但是在 API 上遇到了一些困惑。他们将自己的代码粘贴到了 GitHub 评论区中,但是他们忘记或不知道怎样格式化它,所以他们的代码非常混乱,难以阅读。

你热心地将他们的代码放到一个代码块中,因此它们有一个很友好的格式。但是你仍然需要阅读很多代码。

并且他们对于问题的描述也很难理解。或许这个人不以英文为母语,或者他们有残疾使得他们很难通过写作进行沟通。你不确定。总之,你很难理解他们发布的这一段话。

你很疲劳。你看了看排在他后面的数百个其他人。你可以花费半个小时来理解这个人的代码,或者你可以选择跳过他,只是给他一些教程和文档的链接,这些有助于帮助解决他们的问题。你也可以善意的建议他们尝试 Stack Overflow 或 Slack channel instead。

队伍里的下一个人脸上皱起了眉头。他们抱怨你的项目浪费了他们两个小时,因为某个明确的 API 并没有像宣传的那样如期工作。他们刻薄的言辞让你感觉很不舒服。

你不想在这个人上浪费太多的时间。你简单地回复了:“这是一个开源项目,并由志愿者志愿维护”。如果代码中有一些 bug,请提交一个可复现的测试代码或者一个 PR。

接下来的一个人遇到了一个非常普遍的错误,但是有一个很容易的解决方案。你知道你之前见过这个错误,但是就是想不起来解决方法写在了哪里了。Stack Overflow? wiki? 邮件?Google 了几分钟以后,你粘贴了一个链接并关闭了这个问题。

下一个人是一个长期贡献者。你从各种社区论坛和兄弟项目中认出他们的名字。他们遇到了一个非常深奥的问题,并且提出了一个 pull request 来解决它。不幸地是,这个问题太复杂了,以至于他们的 PR 包含了好几段文字来解释它。

你的眼睛再一次瞥了外面仍然在排队的几百人。你知道这个人在他们的解决方案上做了大量的工作。并且这可能是一个合理的方案。Travis 的测试已经通过了。所以你想回复一个 "LGTM" (译者注:Looks Good To Me.) 然后合并它。

然而,在之前你曾吃过这样的亏。你曾经合并过一个 PR 但是并没有完整的评估它。最后它让你很头痛因为你没有预料到它带来的问题。或许通过了测试,但是性能下降了十分之一。或者造成了内存泄漏。又或者因为导致了这个项目的 API 过于复杂以至于对新用户来说容易困惑。

如果你现在合并了这个 PR,明天你可能会遇到更多的问题,因为你通过解决了这个人的(非常边缘的)问题打破了别人的工作流。因此你决定先将它滞后,稍后当你有更多时间时你会再处理它。

下一个人发现了一个新 bug,但是你知道它实际上是一个兄弟项目中的 bug。他们说这个问题阻止他们运行应用。你知道这是一个大问题,但是只是许多问题中的一个。你现在没有时间来马上修复它。

你回复到看起来这真的是一个问题,但是在另一个 repo 里报告这个问题更合适。因此你关闭了这个问题,并把它复制到另一个 repo 里面。然后添加一个评论建议应该从代码中的哪个地方开始修复它。虽然你怀疑他们是否会这样做。(很少啦)。

接下来的一个人只是说了一句“这是什么状态?”。你不确定他们到底在讨论什么,因此你查看上下文。他们关于一个项目中的长期 bug 的评论导致 GitHub 评论板很冗长。许多人不同意这个问题原本的解决方案,所以它产生了很多讨论。

在这个问题上有 20 多条评论,你需要花费很长的时间才能阅读并理解所有的内容。所以你只是回复了一句:“对不起,这个问题已经打开了有一段时间了,但是到现在还没有人解决它。我们仍在试着理解问题的范围。一个 pull request 或许是一个好的开始。”

下一个人仅仅是一个 GreenKeeper bot。这个处理起来很轻松。除了这个特定的仓库有着相当脆弱的测试,并且因为一个看起来并不真实的原因而测试失败了,因此你为了能够通过测试必须重新启动它。你重启了测试并尝试提醒自己在稍后 Travis 能运行它时检查一下。

接下来的那个人打开了一个 pull request,但是是在一个相当活跃的仓库上,因此另一个维护者已经提出了反馈。你瞥了一眼大致过程,你相信这个维护者能够处理这个问题。因此你将它标记为已读并继续下一步。

下一个人在运行时出现了一个你之前从未见过的大问题。但不幸的是他们没有提供一丁点关于问题实际发生时的细节。用了什么浏览器?Node 的哪一个版本?项目的哪一个版本?使用哪些代码能重现它?你要求他们重新提供一些细节并关闭了这个页面。

The constant stream

过了一段时间后,你已经处理了一二十个这样的情况。但是仍然还有几百个人在等待着。但是现在你已经感到精疲力尽了。每一个人都有他自己的抱怨、问题、或者是新需求。

从某种意义上来说,这些 GitHub 通知就是一个关于你的项目的的不间断消极流。没有人会因为对你的所作所为感到满意时打开一个 issue 或者是 pull request。他们只会在发现缺少一些东西时才这样做。尽管你只花费很少的时间来阅读他们的这些通知,但是仍然能让你在精神上和情绪上感到疲惫不堪。

你的伴侣观察到你在做完这些事情之后总是脾气很坏。或许你发现自己在毫无原因的嘲笑她,仅仅是因为你的心情很糟糕。“如果从事开源工作会让你如此生气,为什么你还要做呢?”她问道。你也没有一个很好的答案。

你可以休息一下。事实上你可以已经尝试过了。之前有一次,你远离 GitHub 给自己放了一两周的假期,仅仅是为了自己的心理健康。但是你知道你结束这种情况的原因是因为有数以百计的人们在耐心地等着你。

如果你保持关注并处理你的 GitHub 通知。或许每天只有 20-30 消息,更容易处理一点。然而你让它们在那里堆积,所以现在堆积了上百个。你感到内疚。

之前,由于某种原因,你真的让这些问题堆积在那了。你或许已经看到有一个问题已经几个月没有回复了。通常,当你回过头处理这样的问题时,打开这个问题的人一直没有给你回复。或者他们回复到:“我放弃了你的项目用了另外一个,所以问题已经解决啦。”这让你感觉很糟糕。但是你理解他们的失望。

从以往的经验中你学到了:对于这种陈旧的问题,更实际的回复是仅仅说一句:“我关闭这个旧问题啦,如果这个问题还存在或者你能提供更多细节的话请再重新打开。”通常情况下都没人回复。有时有人回复了一下,然而只是很生气的抱怨你让他们等待了这么长时间。

现在你尝试更频繁的关注你的通知。数百人的等待队伍实在是太长了。你渴望这个队伍的人数能够降到一百,或十几,甚至有一个 空收件箱 的神话。所以你继续。

招募一个新的贡献者

像上面这样处理了很多问题之后,即使你最终清空了收件箱,仍然会以积压了大量的 bug 和 pull request 而收尾。标签可以对你有所帮助 —— 例如,你可以将一个问题标记为“需要再现”、“存在测试用例”或者 “good first patch”。“good first patch” 尤其有帮助,因为他们常常吸引新的贡献者。

然而,你已经注意到了,通常吸引新贡献者的那些问题都是非常容易的问题 —— 对那些问题而言努力记录并且解释如何修复它比你只是自己修复它还重要。你创建了一些这样的问题,因为你知道让新人参与到开源项目中是值得的,当 pull request 的作者告诉你“这是我第一次向开源项目做出贡献”时,你会感到很开心。

但你知道他们不太可能会回来。通常这些人不会成为长期贡献者或维护者。你想知道你是否做错了,是否有更多你力所能及的可以引领新贡献者并且帮助减轻你的负担的事情。

在你的项目中就有一个几乎是自我维持的。你已经好几年没有碰过它了,但是有一个维护小组在答复每一个问题和 PR,因此你不用关注它。你极其感激这些维护者。但是你并不知道是因为做了什么事情才有如此多的维护者参与这个项目中,而其他的项目则以你独自负责而收尾。

展望未来

你不愿意创建新项目了,因为你知道它只会增加你的维护负担。事实上,有一个对立的现象是:你越成功,你从 GitHub 通知那里得到的“惩罚”就越多。

你仍然可以回忆起创作的激情,从头开始写一个新项目解决之前未解决的问题时的那种喜悦。但是现在你不喜欢这种喜悦,因为任何新项目都会从旧项目中窃取时间。你想知道是否到了正式放弃你的一些旧项目或者 标记它们为不再维护 的时候了。

你想知道在你崩溃之前你还能坚持多久。你之前考虑将开源作为你的日常工作。但是和一些真正将开源作为生活的人聊过之后,你知道这通常意味着可以将一个具体的开源项目作为你的日常工作。但是对你来说并没有什么帮助,因为你有横跨多个领域的 几十个项目,这些都在争夺你的时间。

你最想要的是有更多的项目可以自我维护。你尝试按照所有的 最佳实践:你有一个 CONTRIBUTING.md 和一个行为准则,你热情地向所有提交高质量的 PR 的人发出所有者权限。为每一个项目都做这些事情是非常辛苦的,所以,你并没有对自己想象中的那样勤奋。

自从你知道开源经常被视为一个为享有特权的白人(就像你一样)开设的高档俱乐部后,你也因为这个而感到内疚。所以你因为没有付出足够的努力来修复这些问题而焦虑。

无论如何,你感到内疚:你知道你可以帮助某人解决他们的问题但是反而让他们的问题腐烂了几个月然后关闭它而内疚,或者因为知道某个人在你的仓库发起了他们的第一个 pull request 但是你并没有时间去回复它而内疚,并且你可能还因此致使他们对开源长期感到气馁。你因自己的所作所为而感到内疚,因没能做到的事情感到内疚,并且不想招募更多的人来分担你不幸的内疚经历。

Putting it all together

我上面所说的都是基于我自己的经验。我不能声称代表了所有从事开源软件事业的人,但是这确实是我的感受。

我已经从事开源很长一段时间了(大概 7 年吧),我一直很讨厌抱怨这些事情,因为我担心这会被理解为应当更明白事理的人的夸张的牢*。毕竟,这种情况不是我自己导致的么?只要我愿意我可以随时离开 GitHub,我对任何人都没有义务。

还有,我不应该感激么?我在开源方面的工帮助我在社区获得了名声。我被邀请在一些会议上演讲。我在推特有成千上万的粉丝在听我说的话并且高度尊重我的意见。可以说我之所以得到了微软的工作就是因为我在开源方面的经历。我该抱怨谁?

并且,我知道已经有很多跟我类似的人放弃了。那些人在无影无踪地消失之前曾积极地合并 pull request、修复问题,在博客上写一些关于他们项目的文章。对于其中一些人,我甚至都不会在他们的 repo 上打开 issue,因为我知道他们不会回复。我不会抱怨这些事情,但是我担心我也会走他们的老路。

我已经采取了很多自我保护措施。我不再使用 GitHub 的通知界面了,我使用邮件进行过滤。因此我可以基于项目(不维护的会被忽略掉)或通知类型(提到我的和我评论过的通常优先级更高)分类我的通知。由于通知是邮件,这也有助于我离线工作并且在一个地方处理所有的事情。

我经常会收到蓝色级别的邮件让我支持一个我已经停止维护的项目(例如,我每月至少收到一封关于这一个项目,通常情况下我不会回复他们。我也倾向于忽略我博客文章里面的评论、Stack Overflow 答案的回复和邮件里的问题。我基本上也不再关注那些我觉得别的维护者已经做得很好的 repo。

这种情况如此令人沮丧的原因之一是,我越来越觉得处理问题远比实际维护一个项目要花费时间。换句话说,我经常只有时间阅读一个问题然后说:“对不起,我现在没时间看这个。”仅仅是这样的回复就已经占用了我原本为开源预留的大部分时间。

Issue templates, GreenKeeper, Travis, travis_retry, Coveralls, Sauce Labs… 针对开源维护的问题,有这么多的技术解决方案。我非常感激它们。如果没有这么多自动化工具,我将不能保持专注。但在某些时候,相比技术问题,你遇到的更多的是社交问题。一个人成不了规模。我甚至不在 前 100 个 npm 贡献者 之列,就已经感觉到了压力。简直不敢想象那一百个人的感觉是什么样的。

我已经告诉我的伴侣,当我们决定开始拥有一个孩子时,可能我还是退出开源比较好。我不知道我怎样才能在撑起一个家庭和从事开源之间平衡时间。我预计最终这个将解决我的问题:核选择。我只是希望它能以一个积极的形式到来,像是开启了我的生活新篇章一样,而不是一个消极的形式。

结尾词

如果你已经阅读到这里,并且对开源社区的问题和潜在的解决方案感兴趣,或许你会想看看 Nadia Eghbal 写的 “Roads and Bridges”,这可能是对问题最清晰和最彻底的分析。

我也乐于接受建议,但是请记住,我非常不愿意在我的开源项目中将钱和劳动成果混在一起(由于傻傻的理想主义的原因)。但是我曾在 其他项目 中看到它处理的很好。

注意,尽管上边这些都是消极的,但是我仍然感觉开源已经成为了对我的生活很有价值的补充。但我希望这是一个有用的窗口,它可以感受到如何成为你自己的成功的受害者,并且没有完成就放下工作而感到压力。

如果说我在开源中学到了一件事,那就是:你做的工作越多,你就越需要工作。我知道这个问题无解。

本文根据 Nolan Lawson 的《What it feels like to be an open-source maintainer》所译,整个译文带有自己的理解与**,如果译得不好或有不对之处还请同行朋友指点。如需转载此译文,需注明英文出处:nolanlawson.com/2017/03/05/what-it-feels-like-to-be-an-open-source-maintainer

GoLang 中的随机数

随机数我们都知道,就是计算机通过某种算法,“随机”的生成一个数字。很多编程语言都有内置的方法来生成随机数,那么 GoLang 中是怎样一种情况呢?

伪随机数

我们都知道“随机数”在现实生活中的概念,可能你随手抛一个硬币,就可以说其结果是随机的,但是在计算机中要确定一个“随机数”真的是“随机数”,那可是有标准的,不是你随随便便说是就是。

根据密码学原理,要想对一个“随机数”进行随机性检验有以下几个标准:

  • 统计学伪随机性 - 在给定的随机比特流样本中,1 的数量大致等于 0 的数量,也就是说,“10”“01”“00”“11” 四者数量大致相等。说人话就是:“一眼看上去是随机的”。
  • 密码学安全伪随机性 - 就是给定随机样本的一部分和随机算法,不能有效的演算出随机样本的剩余部分。
  • 真随机性 - 其定义为随机样本不可重现。

根据以上几个标准,其对应的随机数也就分为以下几类:

  • 伪随机数 - 满足第一个条件的随机数。
  • 密码学安全的伪随机数 - 同时满足前两个条件的随机数。可以通过密码学安全伪随机数生成器计算得出。
  • 真随机数 -同时满足三个条件的随机数。

了解了以上几个概念,我们就知道了“伪随机数”其实就是一个“看似随机,实则并不真正随机”的数字。

伪随机数生成器

在实际应用中大部分情况下伪随机数就足够了。这些数列是“似乎”随机的数,实际上它们是通过一个固定的、可以重复的计算方法产生的。因为它们实际上是可以计算出来的,所以它们并不真正地随机,但是它们具有类似于随机数的统计特征。产生这样的结果的生成器我们叫做伪随机数生成器。

一般只有在密码学场景中,我们才需要使用“真随机数”。

在大部分编程语言中,提供的都是“伪随机数生成器”,例如 JS 中的 Math.random()GoLang 中的 math/rand 包。

GoLang 中的伪随机数

GoLang 中,我们可以通过 math/rand 包里的方法来生成一个伪随机数:

package main

import (
  "fmt"
  "math/rand"
)

func main() {
  fmt.Println(rand.Int())   // => 134020434
}

上面的代码中,我们通过 rand.Int() 方法来生成一个伪随机数。看起来好像没什么问题嘛,人家也很 OK 啦。

但是细心的你会发现,你在自己电脑上运行上面的代码竟然和我的一样。无论你怎么运行,它都一样。

我们知道 JS 中的 Math.random() 每次都会返回一个不一样的数字,但是 GoLang 中的伪随机数生成器默认情况下竟然会返回相同的数值,这还不反了天了?

都是伪随机数生成器,为什么差别就这么大呢?这里我们就要了解一下“随机种子”的概念啦。

随机种子

我们知道,伪随机数,是使用一个确定性的算法计算出来的似乎是随机的数序,因此伪随机数实际上并不随机。

那么自然,在计算伪随机数时假如使用的开始值不变的话,那么算法计算出的伪随机数的数序自然也是不变的咯。

这个“开始值”,就被称为随机种子。

查阅文档,我们得知,Int() 函数是从 default Source(默认源)中产生的伪随机数。

而这个 default Source,我们从 Seed 部分可以看到,如果你没有设置随机种子,那么默认初始种子总是从 1 开始。

既然随机种子一样,那自然其结果也是一样的。

随机的伪随机数

我们已经知道了默认随机种子是从 1 开始,那么我们只要在每次生成随机数之前先设置一个不一样的种子,那么其结果自然也就不一样了。

我们要尽可能保证每次伪随机数生成器工作时使用的是不同的种子,通常的做法是采用当前时间作为种子。

package main

import (
  "fmt"
  "math/rand"
  "time"
)

func main() {
  rand.Seed(int64(time.Now().UnixNano()))

  fmt.Println(rand.Int())
}

这样,由于种子不同,我们每次运行的结果也就不一样。我们就能达到获取伪随机数的目的啦。

真随机数

如果我们的应用对安全性要求比较高,需要使用真随机数的话,那么可以使用 crypto/rand 包中的方法。

package main

import (
	"crypto/rand"
	"fmt"
	"math/big"
)

func main() {
	// 生成 20 个 [0, 100) 范围的真随机数。
	for i := 0; i < 20; i++ {
		if result, err := rand.Int(rand.Reader, big.NewInt(100)); err != nil {
			fmt.Println("Error handling: ", err.Error())
		} else {
			fmt.Println(result)
		}
	}
}

上面的程序每次运行的结果都是不一样的,会真正随机的生成随机数。

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.