Skip to content

也谈JavaScript数组去重

2017年1月5日

JavaScript的数组去重是一个老生常谈的话题了。随便搜一搜就能找到非常多不同版本的解法。

昨天在微博上看到一篇文章,也写数组去重,主要推崇的方法是将利用数组元素当作对象key来去重。我在微博转发了“用对象key去重不是个好办法…”然后作者问什么才是推荐的方法。

细想一下,这样一个看似简单的需求,如果要做到完备,涉及的知识和需要注意的地方着实不少,于是诞生此文。

定义重复(相等)

要去重,首先得定义,什么叫作“重复”,即具体到代码而言,两个数据在什么情况下可以算是相等的。这并不是一个很容易的问题。

对于原始值而言,我们很容易想到11是相等的,'1''1'也是相等的。那么,1'1'是相等的么?

如果这个问题还好说,只要回答“是”或者“不是”即可。那么下面这些情况就没那么容易了。

小程序接入OAuth

2016年12月29日

如何使用web录制视频

2016年9月25日

cover

Node.js中低成本实现错误告警

2016年1月27日

相比其他语言(特指PHP)而言,Node.js应用更需要关注出错信息,因为一旦处理不慎,就会导致应用crash。

一种偷懒的方法是使用PM2之类的进程管理软件来启动Node.js进程,从而达到出错crash后自动重新启动应用的目的。

当然更好的办法则是手工捕获错误,然后进行适当的处理,防止应用产生未被接住的错误导致crash。

在捕获到Node.js产生的错误后,下一步自然是记录到错误日志中,以便日后可以进行分析,并针对性地排查修改。本文要说的,即是对错误日志的处理方式之一——告警。

告警是运维工作中非常重要的一个环节,它能让开发者(维护者)及时获知应用出错状态和详情,及早介入处理,将线上故障的影响降低到最低。而要实现告警功能,则需要从两方面入手,一方面是对错误信息进行集中处理(分类、分级、合并、限流等),另一方面需要将这些错误信息及时推送出去。

使用PM2 Deploy部署基于Git版本管理的网站应用

2014年11月19日

按照官方介绍,PM2是一款用于生产环境Node.js应用进程管理的工具。按照民间介绍,它主要有这样几个功能:保证Node.js应用永远在线(挂掉自动重启)、自动负载均衡、零中断重启应用等。

鉴于它是如此优秀,这里还是简要介绍一下前两个功能。

安装

首先,它是一个Node.js写的工具,使用npm即可安装使用:

npm install -g pm2

运行Node.js程序

如果不使用pm2,运行Node.js程序是这样:

node xxx.js

使用pm2,是这样:

pm2 start xxx.js

监视模式

如果你正在开发Node.js应用,需要在代码变更后自动重启应用,只需要在pm2的参数中加上--watch即可:

pm2 start xxx.js --watch

Retina屏下的CSS雪碧图

2014年3月19日

cover

学习ES6生成器(Generator)

2013年12月29日

这几天,TJ大神的koa框架突然在国内火起来了,随之而来的,则是其使用的ES6生成器(Generator)引起了广大码农的强烈兴趣,各种文章也如雨后春笋般拔地而起,比如这篇这篇、还有这篇。这个神奇的生成器被视为解决JS“回调恶魔金字塔”的利器。在动手实践之后,发现介绍ES6生成器的文章仍然有些疏漏,因此有了这篇文章,权当是对各位大大们的补充好了。

背景

在JS的使用场景中,异步操作的处理是一个不可回避的问题,如果不做任何抽象、组织,只是“跟着感觉走”,那么面对“按顺序发起3个ajax请求”的需求,很容易就能写出如下代码(假设已引入jQuery):

javascript
// 第1个ajax请求
$.ajax({
  url:'http://echo.113.im',
  dateType:'json',
  type:'get',
  data:{
    data:JSON.stringify({status:1,data:'hello world'}),
    type:'json',
    timeout:1000
  },
  success:function(data){
    if(data.status === 1){
      // 第2个ajax请求
      $.ajax({
        ......此处省略500字
        success:function(data){
          if(data.status === 1){
            // 第3个ajax请求
            $.ajax({
              ......此处省略500字
              success:function(data){
                if(data.status === 1){

                }
              }
            });
          }
        }
      });
    }
  }
});
// 第1个ajax请求
$.ajax({
  url:'http://echo.113.im',
  dateType:'json',
  type:'get',
  data:{
    data:JSON.stringify({status:1,data:'hello world'}),
    type:'json',
    timeout:1000
  },
  success:function(data){
    if(data.status === 1){
      // 第2个ajax请求
      $.ajax({
        ......此处省略500字
        success:function(data){
          if(data.status === 1){
            // 第3个ajax请求
            $.ajax({
              ......此处省略500字
              success:function(data){
                if(data.status === 1){

                }
              }
            });
          }
        }
      });
    }
  }
});

当顺序执行的异步操作越来越多的时候,回调层级也就越多,这也就是传说中的“回调恶魔金字塔”。

如何设计一个前端模板引擎

2013年8月25日

前端模板引擎现在已经被广泛应用于前端开发了,几乎每个项目都会使用。微博上甚至出现了“不写个模板引擎就没办法在前端界混了”的言论。当然,这是玩笑话,却也能在一定程度上反映前端模板的普及程度。如果你还没有了解过前端模板引擎,赶紧去补补课吧。

本文其实算不上是一篇讲模板引擎设计的文章,写这篇文章的动力来自于自己使用过一些模板引擎(jQuery Tmpl、jade、ejs、artTemplate以及ThinkPHP自带后端模板引擎)之后的心得,所以可能不会涉及到模板引擎设计的方方面面,更多地是讲模板引擎之间的一些有差异的细节以及我的思考和取舍。

来历

javascript
var tempHtml = '<table>' +
    '     <tr>' +
    '       <th>Hello</th>' +
    '       <th>World</th>' +
    '       <th>!</th>' +
    '     </tr>' +
    '     <tr>' +
    '       <td>' + myData.col1 + '</td>' +
    '       <td>' + myData.col2 +'</td>' +
    '       <td>' + (myData.col3 === 'yes'?'!':'?') + '</td>' +
    '     </tr>' +
    '   </table>';

document.querySelector('#myDiv').innerHTML = tempHtml;
var tempHtml = '<table>' +
    '     <tr>' +
    '       <th>Hello</th>' +
    '       <th>World</th>' +
    '       <th>!</th>' +
    '     </tr>' +
    '     <tr>' +
    '       <td>' + myData.col1 + '</td>' +
    '       <td>' + myData.col2 +'</td>' +
    '       <td>' + (myData.col3 === 'yes'?'!':'?') + '</td>' +
    '     </tr>' +
    '   </table>';

document.querySelector('#myDiv').innerHTML = tempHtml;

相信上面的代码对哪怕做过一点点涉及界面开发的都应该很熟悉吧。当我们想把一段结构和一段数据组合起来,再放到页面上时,就会常常面临这样一段复杂的代码。

这段代码相信不用我说你也会觉得它实在有点复杂:要处理结构中字符串本身的拼接,还要注意结构与数据的拼接,处理数据拼接时还要注意运算优先级(尤其在使用?:三元运算符时),还要为了可读性考虑纠结的缩进……

当然,最麻烦的还不是这里,当我们想要对一个数据循环遍历并输出时,居然还要自己去写循环,再一圈一圈地把这些结构拼起来,最后再拼上首尾的结构。而当数据为空时,又要自己去写一个“暂无数据”之类的占位符……

为什么浏览器不内建更多选择器

2012年9月6日

来自知乎问题JavaScript 为什么不内建选择器?

首先,与这个问题有关的浏览器中的技术概念其实大致有这些:

  1. BOM,即浏览器对象模型,简单说就是浏览器提供的环境,包括各种对象及其方法,比如window
  2. DOM,即文档对象模型,它是由HTML经解析后生成的一个模型,我们对页面可视部分进行操作实际上就是在操作DOM
  3. JavaScript,浏览器提供了BOM,也解析了DOM,那么,开发者如何去操作它们呢?这时候就轮到JavaScript出场了,所以JavaScript(在这个例子中)是用来操作DOM和BOM的

那么所谓的选择器,getElement(s)ByXXXX实际上是由DOM提供的,而且对DOM的level实现的程度不一样,这些方法也不一样,比如DOM level 0中主要的方法(确切说是属性)就是document.imagesdocument.links之类。而DOM level 3中则提供了querySelector(All)之类更为方便的API。

[译]什么是Shadow Dom?

2012年6月7日

cover

xheditor从剪贴板粘贴图片的实现原理

2011年11月30日

xheditor是一个优秀的国产富文本编辑器,最近的(其实我也不知道有多久了)版本推出了一个粘贴剪贴板图片的功能,很是喜爱,好奇了好久,最终不住去看了下源码,基本明白了。

2016-07-29 似乎这个编辑器也很久没更新了,现在对上面这段话持保留态度,不做推荐。

首先,这个功能很新,不支持IE系列浏览器……用的是一些新的API。我手上的代码是1.1.10,所以代码行数以这个版本为准。

一点前置小知识是必备的,那就是对大部分截图软件来说,截图操作是一个把截取的图片转换成指定格式(windows自带的是bmp)然后放入剪贴板的过程。所以,要粘贴图片,核心就是读取剪贴板。

纪念网易笔试错题

2010年9月28日