两个键盘事件的兼容问题

最近碰到两个键盘事件的问题,以前一直没怎么注意。

中文输入法的回车问题

很多输入框都支持Enter回车键提交,但是在中文输入法下,用回车输入英文的时候会直接触发Enter提交行为。此时可以使用KeyboardEventisComposing属性可以判断当前是否是处于输入过程中,即是否在compositionstartcompositionend之间,如果isComposingtrue,忽略此时的Enter即可。在FirefoxChrome中都无此问题,但是在Safari下,此时的isComposing会为false,无法正常处理此时的Enter

迫于无奈,只好看下Event中是否还有其他属性可以使用,试试keycode和被抛弃的keyCode

console.log(e.key, e.code, e.keyCode, e.isComposing)

Chrome / Edge 结果如下:

Firefox

useSignal()——前端框架的未来?

Angular以及Qwik的作者MIŠKO HEVERY写了篇文章:useSignal()才是Web框架的未来(useSignal() is the Future of Web Frameworks),也引起一些讨论。包括Qwik在内的多个框架也已经实现了useSignal(),这些框架还有Vue、Preact、Solid以及Svelte等。

实际上signals并不是一个全新的概念,大约十年前的框架Knockout就曾经使用过。那为什么最近突然又重提此项技术?这主要得益于当今更加先进的编译技巧以及与jsx的深度集成,使signals的开发体验变得更好了。

什么是signal

如果了解过React的话,signal其实和useState非常类似,也是一种用来存储应用状态的方式。但是和useState存在一些区别:

useState是返回一个值以及一个set方法,而useSignal则是返回一个getter和一个…

看到一个刁钻问题: (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',

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) 

js中函数预解析在Firefox下的异常表现

前几天同事发现的一个诡异现象,猜猜浏览器执行下面这段代码会弹出什么提示?

if(1){
    f(1);
    function f(a){
        alert(a);
    }
}

通常情况下,都认为javascript中function会被预解析,所以这里应该会弹出一个对话框,显示字符“1”。没错,在IE6-IE9,Chrome,Safari,Opera等待浏览器下也都是这个结果。但是偏偏Firefox有点特立独行,会提示“引用错误,f未定义”。

我们再试试,把if去掉,只留两个花括号看看:

{
    f(1);
    function f(a){
        alert(a);
    }
}

还是一样!现在我们在试试几种情况:

if(1){
    function f(a){
        alert(a);
    }
    f(1);
}

这个没有问题,正常显示1,再试试这个:

if(1){
    function f(a){
        alert(a);
    }
}
f(1);

也没有问题,再试试这个:

if(0){
    function f(a){
        alert(a);

也谈JavaScript代码性能优化

差不多两年前写了个选择器whiz,除在DOM查找方面做了许多优化工作之外,还在代码优化上做了很多工作,一直没有分享。抽空总结一下,基本上在jQuery、Mootools和YUI的源码里面都可以看到这些写法。有些是已经在网上分享很多遍了,众所周知的,也有一些可能写了多年的JavaScript的开发人员也不一定想得到的。如果有说得不正确的地方,还请大家指出。还有特别说明的是,其中某些写法不是很推荐,虽然代码简洁了,但是有可能造成阅读困难。

1.尽量使用源生方法(Native Method)

js是解释性语言,相比编译性语言执行速度要慢。如果浏览器已经实现了该方法,就不要再用js再去实现一遍了。另外,绝大部分情况下,浏览器已经实现的方法已经在算法方面做了很多优化,再重复实现一遍只是浪费时间和精力还有带宽。当然,如果你只是为了练习算法,那另当别论。

2.尽可能减少循环次数

代码的瓶颈大多在循环,少一层循环,就能数倍地提高性能。如果要对一个数组的每个元素进行多次操作,尽可能使用一次循环,多次操作,而不是多次循环,每次循环执行一次操作。尤其是在进行多个正则匹配的时候,尽可能合并正则表达式,在一次遍历中尽可能找到相应的匹配。…

Merpressor —— 在线自动合并、压缩JS文件

最近工作稍微空了点,正好又有幸见到了盛大的在线合并工具,于是一时兴起,把YUI Compressor改造了一下,写了个在线合并JS和CSS的工具,命名为Merpressor,目前已经在工作中使用了。

Mepressor分为两个部分:一部分为公网发布时所用,使用Java编写;另一部分为本地调试时所用,使用轻量和方便的PHP编写。(似乎很绕,简单地讲:Java版本用来公网部署,合并同时压缩代码;PHP版用来本地测试,并不压缩内容。)

在项目中需要合并多个js文件或者css文件时,前端开发者只需修改一个xml格式的配置文件,指定需要合并的文件,通过一定的规则访问,服务器则可自动合并多个js文件,并使用YUI Compressor压缩后返回相应内容,而本地环境下,则会自动导入xml中指定的多个js文件或者css文件,从而使得开发调试和发布一体化,真正做到无缝切换。

注意: 由于合并和压缩需要花费较大的资源和时间,因此在响应速度和并发上会表现较差,在实际使用过程中,需要配合CDN(内容分发网络,一般中大型网站都会采用)使用。当然,你也可以只是把这个工具当合并压缩工具使用。…

在弹出窗口用POST提交数据

话说离上一篇日志的发表时间已有漫长的四个多月,实在是对不住读者。客观原因找一下,但是还是要实事求是:一是因为工作实在是太忙太累,无暇顾及;二是BLOG系统太慢,从前到后都需要大概,在开忙之前想修改BLOG系统来着,结果改了一点点就开始忙得不可开交了,于是也中止了。

春节休息了几天,今天上班第一天,最近混twitter混得比较多,经常要压缩URL,以前做了个书签http://is.gd/压缩,后来发现了全球最短的URL——http://to./,于是决定换API压缩。以前的API可以用GET方式提交数据压缩,但是这个却需要用POST方式提交,因此需要在弹出窗口的同时用POST提交数据。实现起来很简单:在弹出窗口中生成一个表单,把value写到对应的字段中,打开弹出窗口后再用js提交表单即可。

代码如下:

javascript: void(function() {
	var p = 'http://to./',