一组随之飘过的 JavaScripters 的聊天记录

随着网络的发展,聊天软件日益成为人类生活中不可或缺的一部分。日常刷屏的人屡见不鲜。 今年不知怎么着就遇到了一群老厉害的人了,身在世界各地,说着不同的语言,commit 着各式各样的代码。 每天和他们聊天都感觉157个人的群里有156个大神和一个我。每天我就在群里窥着,想着能有一天插上话。 但是现实总是残酷的,从来都不敢说话。 不知道我前面扯了这么多能不能把我 blog 的 description 占掉,因为我嫌首页出现下面那么长的图不好看。

就这样,一场高端水准的 JavaScripter 交流随之开始:

第一个解决方案随之而来:

随后第二个解决方案马上出现:

接着有人提出了关于这两个方法快慢的疑问:

随后有人通过 jsperf 检测了这两种方法的速度:

从图片来看,似乎 split 比 match 快一倍!

然后,@Zac 做出了疑问,是否 for 会更快

直接抛出 perf 后,群主众人提出了异议

提出 length 的检测结果:

虽然对刚刚的逻辑有一些不满意

但是也没有去优化

接下来 @该群已解散 提出了新的方案

结果是:

后来发现 replace 写错了。

最后 @Zac 把 var i 提出来了

看起来快了那么那么多,可惜的是… 他写错了代码

后来,他把代码改好了

发现还是 split 快

后来 @hugo 发了新 perf

第一个是 for ,第二个是 split,这里是 for 快。

接着 @rannn🐨 发了一个

但是 @Zac 又发了一个

for 最快,不过他们两个的写法不太一样。

对比两个人的 for3 和 for charCodeAt。

他们两个除了用的终端不一样以外,for3 进入下一次循环的时候跳过了“飘”后面那个字,

虽然这样可能存在问题,比如“飘”后面根本不是“过”而是“飘过的话,就会少检索一个。

不过是在这个题里是可用的,这个题“飘”后面都是“过”。 但是为了完美,我们稍作改动

var count = 0;
var len = data.length;
for(i = 0;i < len;){
  if(data.charCodeAt(i++) === 39128 && data.charCodeAt(i) === 36807){
        count++;
        i ++;
    }
}

就上面的几个模糊不清的例子

到底怎么样才快呢….

亲自试一下吧

split 方案

var count = data.split('飘过').length - 1;
count;

改良过的跳过“过”字的版本

var count = 0;
var len = data.length;
for(i = 0;i < len;){
  if(data.charCodeAt(i++) === 39128 && data.charCodeAt(i) === 36807){
        count++;
        i ++;
    }
}
count;

有修改的 @rannn🐨 的

var count = 0;
var len = data.length;
for(var i = 0;i < len;i++){
  if(data.charCodeAt(i) === 39128 && data.charCodeAt(i+1) === 36807){
        count++;
    }
}
count;

@rannn🐨 他的 i 是没有 被 var 的

var count = 0;
var len = data.length;
for(i = 0;i < len;){
  if(data.charCodeAt(i++) === 39128 && data.charCodeAt(i++) === 36807) count++;
}
count;

@Zac

var count = 0;
var len = data.length;
var i = 0;
for(i;i < len;i++){
  if(data.charCodeAt(i) === 39128 && data.charCodeAt(i+1) === 36807)
        count++;
}
count;

我的机器(chrome58):

我朋友的机器(chrome57):

从我的机器上测试可以看出,for 是别 split 要快

稍等,我发现 for 1 里面的 i 也没有定义,我把 for 1 里面的 i 提取和出来定义看一下。

发现,for 1 变成了最快的。使用 var 关键字来定义 i 可以提升效率?

@Zac的 和 for 2 是差不多的,但是 @Zac 将 var i = 0 提出来了,稳定性上提升了不少。

总结上面的经验,我写下了我的代码:

var count = 0;
var len = data.length;
var i = 0;
for(;;){
   if (data.charCodeAt(i) == 39128 && data.charCodeAt(i + 1) == 36807) {
        count ++;
    } else if (data.charCodeAt(i) == 36807 && data.charCodeAt(i - 1) == 39128) {
        count ++;
    }
   i+=2
  if (i >= len) break;
}
count;

再做一次测试(chrome58):

我的手机 safari

我朋友的机器(chrome57):

我用了我机器上的(chrome60)

在金丝雀版里的 @Zac是最快的,var i = 0 提不提取影响不大。

所以我在想,是否不需要提取 var i = 0 也不需要对for循环做一些参数的优化会比较快呢?

果然!我修改了一下,剧情再次反转!

那么问题来了!

  • 为什么 chrome57 上 splitfor 快?
  • chrome60 对 for 循环做了哪些优化?
  • 等等

测试地址:

https://jsperf.com/splite-for-pg