看到一个刁钻问题: (a==1 && a==2 && a==3) 可以为true吗?

一看到这个刁钻问题,我竟然有点懵: (a==1 && a==2 && a==3) 是否可以为true?既然能提出这个问题,说明那肯定是可以为true的,那么怎么样实现呢?

在js里面,比较运算符对于不同类型的值会做类型转换,所以这里应该有可以操作的可能。我们先看一下非严格相等在js里面的类型转换关系:

被比较值 B
Undefined Null Number String Boolean Object
被比较值 A Undefined true true false false false IsFalsy(B)
Null true true false false false IsFalsy(B)
Number false false A === B A === ToNumber(B) A=== ToNumber(B) A== ToPrimitive(B)
String false false ToNumber(A) === B A ===

为什么parseInt(0.0000007)结果为7?

一个看似奇怪的问题,正常我们预期这个结果应该是0才对,结果却是7,令人意外。参考ECMAScript标准里面的描述

The parseInt function produces an integral Number dictated by interpretation of the contents of the string argument according to the specified radix. Leading white space in string is ignored. If radix is undefined or 0, it is assumed to be 10 except when the number begins with the code unit pairs 0x or 0X, in which case a radix of 16 is assumed. If radix is 16, the number may also optionally begin with

[翻译]为什么我们放弃了使用CSS-in-JS

我是Sam,Spot的一位软件工程师,也是Emotion库第二活跃的维护者。Emotion是一个在React项目中被广泛使用的CSS-in-JS库。这篇文章将深入探究最初吸引我使用CSS-in-JS的原因,以及为什么我(及Spot团队的其他成员)又决定放弃它。

我们将从CSS-in-JS的概述开始,并简要介绍一下它的优缺点。然后,我们再深入探究在CSS-in-JS在Spot上引发的性能问题,以及如何避免它。

什么是CSS-in-JS?

顾名思义,CSS-in-JS允许你直接在JavaScript或TypeScript中写入CSS来设置你的React组件样式:

// @emotion/react (css prop), with object styles
function ErrorMessage({ children }) {
  return (
    <div
      css={{
        color: 'red',
        fontWeight: 'bold',

Electron打包React应用空白的问题

Electron的真的是够折腾的,用React写个APP,dev的时候看起来挺正常的,打包出来一片空白。

打开调试工具看了一下,发现是加载不到页面。于是把asar包拖出来解压看了一下,发现页面加载路径似乎不太对,在main.js里面调整一下:

mainWindow.loadURL(isDev ? 'http://localhost:3000' : `file://${__dirname}/../build/index.html`);

顺便调整一下打包目录,目前Electron Forge是把整个项目目录都打包进去了,在forge.config.js里面:

packagerConfig: {
  ...
  "dir": "./build",
  ...
},

好了,页面倒是可以加载出来了,发现js路径不对,遗漏了一个很重要的地方。React默认使用了绝对路径,所有的引用都是相对于根目录的,所以还要改下package.json里面的配置,在根下指定:…

Electron在macOS上打包windows exe文件

试着玩一下Electron,在macOS 12/13上打包exe文件时,踩了好几个坑,做个记录。

打包工具使用的是Electron快速入门教程里面推荐的 Electron Forge,在macOS上打包exe文件,需要依赖几个工具:wine、mono、xquartz,分别安装。然后执行打包命令,发现会卡在这个地方:

We need to package your application before we can make it
√ Preparing to Package Application for arch: x64
√ Compiling Application
√ Preparing native dependencies
√ Packaging Application
Making for the following targets:
× Making for target: squirrel - On platform: win32 - For arch: x64

rollup打包处理注释的一个奇怪bug

用了个第三方zip压缩库,正常html用标签方式引入没有问题,用npm引入后发现不支持import,于是跑去github上翻了下issue,结果作者认为import不是正式标准,不打算支持,甚至有人push了修改后的代码,仍然被拒了,原因是破坏了原有的require路径。

这个也好办,把dist下的代码复制过来,加个export default就行了。结果发现下在打包时出现了奇怪的语法错误“SyntaxError: Unexpected token”,通过大段删代码的方式总算定位到一个注释的问题:

const _tr_tally = (s, dist, lc) =>
//    deflate_state *s;
//    unsigned dist;  /* distance of matched string */
//    unsigned lc;    /* match length-MIN_MATCH or unmatched char (if dist==0) 

Sublime Text 2的Less2Css插件介绍与安装

Sublime Text 2这个编辑器应该不用再介绍了,配合各种插件使用起来非常方便,今天要介绍的是一款Sublime Text 2的插件——Less2Css。这款插件的名字已经表明了它的作用——把less文件转换为css文件。

Less2Css插件特性

Less2Css插件的目前主要的功能包括:

  1. 当保存less文件的时候自动生成同名的css文件;
  2. 当保存less文件的时候提示编译错误信息;
  3. 批量编译项目目录下的所有less文件为css文件。

Less2Css未来还会增加@imports功能支持,能够同时自动编译其他引用了此less文件的文件。

安装Less2Css插件

Less2Css可以通过Sublime Text 2的包管理器(Package Control)来安装(强烈建议安装包管理器!安装方法很简单,可以参考前端观察的介绍或者官方文档)。安装完包管理器之后,需要重启Sublime Text 2。

安装Less2Css的方法如下:…

WebSocket Draft 10向客户端写文本数据的实现

在Draft 10中,如果解析数据的过程弄清楚了,这个就更简单了,返回数据的格式和之前接受到的数据格式非常类似,只是你不用生成mask了,头部的其他格式还是一模一样的。

第一个字节还是固定的,是0x81,意义和接受数据的意义一样,第二个字节也是,后七个位表示数据长度,由于没有mask,所以第一位是0;长度的表示方法和接受的标识方法一致,可能用7位表示,也可能用16位表示。

用NodeJS实现如下:

var socketWriter = {
    'draft10': function(socket, data){
        var frames,
            length = new Buffer(data, 'utf8').length;
        if(data.length 0x7d){
            frames = new Buffer(4);
            frames[0] = 0x81;
            frames[1] = 0x7e;
            frames[2] = length 8;
            frames[3] = length & 0xFF;

WebSocket草案10文本数据解析实现

握手协议实现了,接下来就是解析数据了,这个相对来说要麻烦很多,相比草案7.6变得更复杂了。下图是数据传输的格式:

各个值的具体含义可以参考这个中文翻译:http://blog.csdn.net/fenglibing/article/details/6852497,英文原文在这里:http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-10#section-4.2

简单概括一下就是:FIN一直为1,RSV1、RSV2、RSV3一直为0,当发送内容为文本时,opcode为1,MASK如果为1就使用掩码,需要获取四位掩码,依次轮流和数据做异或运算,第一个内容数据与第一个掩码异或,第二个内容数据与第二个掩码异或……第五个内容数据与第一个掩码异或……一直到结束,然后再对内容进行编码就可以了。

在Chrome/Firefox下面,FIN永远为1,如果只是文本消息,opcode一直是1,RSV1、RSV2、RSV3都为0,所以第一个数据是0x81;MASK为1,再跟上数据长度,所以第二个数据会大于0x80,由于数据长度不一样,其需要占用的字节数也不一样,因此掩码的位置也不一样。根据规范,换算下来是这样:数据总长度(包含FIN、RSV等等信息)小于0x84,则掩码为第三个数据到第六个数据;数据总长度(包含FIN、RSV等等信息)小于0xfe81,则掩码为第五个数据到第八个数据;其他掩码则为第十三个数据到第十六个数据。当数据长度超过一个包的长度时,后面的数据包不再包含RIN、RSV和MASK等信息,二是直接为内容数据,需要根据上一次取到的MASK来做异或运算。…

WebSocket草案10握手协议的实现

Chrome早就采用了websocket草案10的协议,很多以前支持websocket的代码突然之间都用不了了,很多作者也没空更新,索性自己看了下草案,自己实现了一套。

握手协议还是非常简单的,Chrome发过来的header大概是这样的:

GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Origin: http://example.com
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 8

要答复的头大概是这样的:

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: