10 Small Things You May Not Know About Javascript

t doesn't matter how many years I've been dealing with Javascript – it contains many little things that surprises me almost every week. For me, Javascript means a constant learning process.

In this article, I'll provide ten small Javascript tips, mainly aimed for beginner and intermediate Javascript developers. Hopefully there's at least one useful tip for every reader :).

1. Variables conversions

This sounds quite obvious, but as far I've seen, using object constructors, like Array()or Number() for converting variables is quite common practice.

Always use primitive data types (sometimes referred as literals) for converting variables. These won't do any extra tricks and they usually have better performance.

  1. var myVar   = "3.14159",  
  2.     str     = ""+ myVar,//  to string  
  3.     int     = ~~myVar,  //  to integer  
  4.     float   = 1*myVar,  //  to float  
  5.     bool    = !!myVar,  /*  to boolean - any string with length 
  6.                             and any number except 0 are true */  
  7.     array   = [myVar];  //  to array  

Converting to dates (new Date(myVar)) and regular expressions (new RegExp(myVar)) must be done with constructors. However, always use /pattern/flags when creating regular expressions.

2. Converting decimals to hex or octals and vice versa

Are you writing separate functions for hex (or octal) conversios? Stop. This can be easily done with existing methods:

  1. (int).toString(16); // converts int to hex, eg 12 => "C"  
  2. (int).toString(8);  // converts int to octal, eg. 12 => "14"  
  3. parseInt(string, 16) // converts hex to int, eg. "FF" => 255  
  4. parseInt(string, 8) // converts octal to int, eg. "20" => 16  

3. More playing with numbers

In addition to previous section, here are some more small tricks with when dealing with numbers.

  1. 0xFF; // Hex declaration, returns 255  
  2. 020; // Octal declaration, returns 16  
  3. 1e3; // Exponential, same as 1 * Math.pow(10,3), returns 1000  
  4. (1000).toExponential(); // Opposite with previous, returns 1e3  
  5. (3.1415).toFixed(3); // Rounding the number, returns "3.142"  

4. Javascript Version Detection

Are you aware which version of Javascript your browser supports? If not, checkJavascript Versions sheet from Wikipedia.

For some reason, features in Javascript version 1.7 are not widely supported. However, most browsers released within a year support features in version 1.8 (and in 1.8.1).

Note: all the versions of Internet Explorer (8 and older) supports only Javascript version 1.5.

Here's a tiny script both for detecting the version of Javascript via feature detection. It also allows checking support for specific version of Javascript:

  1. var JS_ver  = [];  
  2.   
  3. (Number.prototype.toFixed)?JS_ver.push("1.5"):false;  
  4. ([].indexOf && [].forEach)?JS_ver.push("1.6"):false;  
  5. ((function(){try {[a,b] = [0,1];return true;}catch(ex) {return false;}})())?JS_ver.push("1.7"):false;  
  6. ([].reduce && [].reduceRight && JSON)?JS_ver.push("1.8"):false;  
  7. ("".trimLeft)?JS_ver.push("1.8.1"):false;  
  8.   
  9. JS_ver.supports = function()  
  10. {  
  11.     if (arguments[0])  
  12.         return (!!~this.join().indexOf(arguments[0] +",") +",");  
  13.     else  
  14.         return (this[this.length-1]);  
  15. }  
  16.   
  17. alert("Latest Javascript version supported: "+ JS_ver.supports());  
  18. alert("Support for version 1.7 : "+ JS_ver.supports("1.7"));  

5. window.name for simple session handling

This one is something I really like. You can assign values as a string for window.nameproperty and it preserves the values until you close the tab or window.

Although I'm not providing any script, I strongly suggest you to take full advantage from it. For instance, it's very useful for toggling between debugging and (perfomance) testing modes, when building a website or an application.

6. Testing existence of property

This issue can be approached at least from two directions. Either we check whether property exists or we check the type of property. But always avoid these small mistakes:

  1. // BAD: This will cause an error in code when foo is undefined  
  2. if (foo) {  
  3.     doSomething();  
  4. }   
  5.   
  6. // GOOD: This doesn't cause any errors. However, even when  
  7. // foo is set to NULL or false, the condition validates as true  
  8. if (typeof foo != "undefined") {  
  9.     doSomething();  
  10. }  
  11.   
  12. // BETTER: This doesn't cause any errors and in addition  
  13. // values NULL or false won't validate as true  
  14. if (window.foo) {  
  15.     doSomething();  
  16. }  

However, there may be situations, when we have deeper structure and proper checking would look like this:

  1. // UGLY: we have to proof existence of every  
  2. // object before we can be sure property actually exists  
  3. if (window.oFoo && oFoo.oBar && oFoo.oBar.baz) {  
  4.     doSomething();  
  5. }  

7. Passing arguments for function

When function has both required and optional parameters (arguments), eventually we may end up with functions and function calls looking like this:

  1. function doSomething(arg0, arg1, arg2, arg3, arg4) {  
  2. ...  
  3. }  
  4.   
  5. doSomething('''foo', 5, [], false);  

It's always easier to pass only one object instead of several arguments:

  1. function doSomething() {  
  2.     // Leaves the function if nothing is passed  
  3.     if (!arguments[0]) {  
  4.         return false;  
  5.     }  
  6.   
  7.     var oArgs   = arguments[0]  
  8.         arg0    = oArgs.arg0 || "",  
  9.         arg1    = oArgs.arg1 || "",  
  10.         arg2    = oArgs.arg2 || 0,  
  11.         arg3    = oArgs.arg3 || [],  
  12.         arg4    = oArgs.arg4 || false;  
  13. }  
  14.   
  15. doSomething({  
  16.     arg1    : "foo",  
  17.     arg2    : 5,  
  18.     arg4    : false  
  19. });  

This is only a rough example of passing an object as an argument. For instance, we could declare an object with name of the variable as keys and default values as properties (and/or data types).

8. Using document.createDocumentFragment()

You may need to dynamically append multiple elements into document. However, appending them directly into document will fire redrawing of whole view every time, which causes perfomance penalty. Instead, you should use document fragments, which are appended only once after completion:

  1. function createList() {  
  2.     var aLI = ["first item""second item""third item",  
  3.         "fourth item""fith item"];  
  4.   
  5.     // Creates the fragment  
  6.     var oFrag   = document.createDocumentFragment();  
  7.   
  8.     while (aLI.length) {  
  9.         var oLI = document.createElement("li");  
  10.   
  11.         // Removes the first item from array and appends it  
  12.         // as a text node to LI element  
  13.         oLI.appendChild(document.createTextNode(aLI.shift()));  
  14.         oFrag.appendChild(oLI);  
  15.     }  
  16.   
  17.     document.getElementById('myUL').appendChild(oFrag);  
  18. }  

9. Passing a function for replace() method

There are situations when you want to replace specific parts of the string with specific values. The best way of doing this would be passing a separate function for method String.replace().

Following example is a rough implementation of making a more verbose output from a single deal in online poker:

  1. var sFlop   = "Flop: [Ah] [Ks] [7c]";  
  2. var aValues = {"A":"Ace","K":"King",7:"Seven"};  
  3. var aSuits  = {"h":"Hearts","s":"Spades",  
  4.             "d":"Diamonds","c":"Clubs"};  
  5.   
  6. sFlop   = sFlop.replace(/\[\w+\]/gi, function(match) {  
  7.     match   = match.replace(match[2], aSuits[match[2]]);  
  8.     match   = match.replace(match[1], aValues[match[1]] +" of ");  
  9.   
  10.     return match;  
  11. });  
  12.   
  13. // string sFlop now contains:  
  14. // "Flop: [Ace of Hearts] [King of Spades] [Seven of Clubs]"  

10. Labeling of loops (iterations)

Sometimes, you may have iterations inside iterations and you may want to exit between looping. This can be done by labeling:

  1. outerloop:  
  2. for (var iI=0;iI<5;iI++) {  
  3.     if (somethingIsTrue()) {  
  4.         // Breaks the outer loop iteration  
  5.         break outerloop;  
  6.     }  
  7.   
  8.     innerloop:  
  9.     for (var iA=0;iA<5;iA++) {  
  10.         if (somethingElseIsTrue()) {  
  11.             // Breaks the inner loop iteration  
  12.             break innerloop;  
  13.         }  
  14.   
  15.     }  
  16. }  

Afterwords

Go ahead and comment! Did you learn anything new? Do you have good tips to share? I'm always delighted for sharing information about all the little details in Javascript.

15款很棒的 JavaScript 开发工具

在开发中,借助得力的工具可以事半功倍。今天,这篇文章向大家分享最新收集的15款非常有用的 JavaScript 开发工具。
TestSwarm: Continious & Distributed JS Testing

TestSwarm是Mozilla实验室推出的一个开源项目,它旨在为开发者提供在多个浏览器版本上快速轻松测试自己JavaScript代码的方法。
Javascript-212 in Useful JavaScript and jQuery Tools, Libraries, Plugins

Minimee
在网络上,速度是很重要的,Minimee能帮助你将CSS和JavaScript文件进行自动压缩和打包。
Javascript-169 in Useful JavaScript and jQuery Tools, Libraries, Plugins

Doctor JS
Doctor JS 是一款帮你分析 JavaScript 代码的工具,测试你的代码在多态、原型、异常和回调方面写得怎么样。
Javascript-174 in Useful JavaScript and jQuery Tools, Libraries, Plugins

Remy Sharp's JSConsole
一个在线的 JavaScript 控制台工具,对于测试、调试和演示非常有用。
Javascript-269 in Useful JavaScript and jQuery Tools, Libraries, Plugins

JavaScript Library Boilerplate
JavaScript Library Boilerplate 帮助你随时随地创建自己的 JavaScript 库。
Javascript-260 in Useful JavaScript and jQuery Tools, Libraries, Plugins

jsdoc-toolkit
JsDoc Toolkit 是一款辅助工具,你只需要根据约定在 JavaScript 代码中添加相应的注释,它就可以根据这些注释来自动生成API文档。
Js-010 in Useful JavaScript and jQuery Tools, Libraries, Plugins

Jasmine: BDD for your JavaScript
Jasmine 是一个有名的javascript单元测试框架,它是独立的"行为驱动开发"框架。
Js-011 in Useful JavaScript and jQuery Tools, Libraries, Plugins

ObfuscateJS: JavaScript compressor
一款 JavaScript 混淆工具,去除空白和注释,重命名变量等。
Javascript-282 in Useful JavaScript and jQuery Tools, Libraries, Plugins

PEG.js
PEG.js 是一个JavaScript的表达式语法解析器,它使您能够轻松地建立复杂的数据或计算机程序语言的快速分析器。
Javascript-228 in Useful JavaScript and jQuery Tools, Libraries, Plugins

JSONView
JSONView 是一款帮助你在浏览器中查看JSON文档的Firefox插件。
Js-014 in Useful JavaScript and jQuery Tools, Libraries, Plugins

JSonduit
JSonduit 是一个将网页内容转换为 JSON 格式订阅器的工具。
Javascript-182 in Useful JavaScript and jQuery Tools, Libraries, Plugins

jsplumb
jsPlumb 为开发者提供了可视化链接元素到页面的方法,可以结合jQuery、MooTools 和 YUI3使用。
Javascript-193 in Useful JavaScript and jQuery Tools, Libraries, Plugins

Helma
Helma 是一个用来开发快速、稳定的Web应用程序的开源框架,它使用JavaScript 来作为服务端脚本环境,从而可以省略编译周期。
Js-015 in Useful JavaScript and jQuery Tools, Libraries, Plugins

HTML + JSON Report
一款将 JSON 数据转换为可读性更高的HTML格式内容的在线工具。
Javascript-300 in Useful JavaScript and jQuery Tools, Libraries, Plugins

JSON Editor
这个编辑器可以帮助你方便的编辑 JSON 字符串。
Javascript-222 in Useful JavaScript and jQuery Tools, Libraries, Plugins
你可能还喜欢

  • 推荐40个优秀的免费CSS工具
  • 分享18个常用的网站性能测试工具
  • 推荐25个提高网站可用性和转化率的工具
  • JavaScript初学者应注意的七个细节
  • 你可能不知道的10个JavaScript小技巧
  • 推荐19个很有用的 JavaScript 库

    流行的 JavaScript 库有jQuery,MooTools,Prototype,Dojo和YUI等,这些 JavaScript 库功能丰富,加上它们众多的插件,几乎能实现任何你需要的功能,然而需要实现一些特定的功能,则可以选择功能更专一的轻量库,今天这篇文章与大家分享16个很有用的 JavaScript 库。

    Blackbird: Open Source JavaScript Logging Utility
    Blackbird 是一款非常酷的 JavaScript 调试工具,带有一个漂亮的界面显示和过滤调试信息。
    Javascript-199 in Useful JavaScript and jQuery Tools, Libraries, Plugins
    Treesaver.js
    Treesaver 是一个用于创建杂志布局的 JavaScript 框架。
    Js-001 in Useful JavaScript and jQuery Tools, Libraries, Plugins
    Bibliotype
    Bibliotype 是一个简单的基于 HTML、CSS 和 JS ,用于快速原型制作的的框架。
    Useful-tool-127 in Useful JavaScript and jQuery Tools, Libraries, Plugins
    Highcharts – Interactive JavaScript charts
    Highcharts 是一个纯 JavaScript 编写,用于生产交互式图表的 JavaScript 库。
    Javascript-264 in Useful JavaScript and jQuery Tools, Libraries, Plugins
    jStat: a JavaScript statistical library
    Stat是一个采用JavaScript开发的统计工具包,可以让你执行高级统计操作,而不需要专门的统计语言。
    Js-007 in Useful JavaScript and jQuery Tools, Libraries, Plugins
    highlight.js
    Highlight.js 是一个用于高亮显示程序代码的 JavaScript 库,简单易用。
    Javascript-268 in Useful JavaScript and jQuery Tools, Libraries, Plugins
    Respond.js: Fast CSS3 Media Queries for Internet Explorer 6-8 and More
    这个快速、轻量的库用于让IE6-8支持 CSS3 Media Queries,是一种让网页支持小屏幕设备显示的特性。
    Javascript-154 in Useful JavaScript and jQuery Tools, Libraries, Plugins
    Underscore.js
    Underscore 是一个实用的JavaScript工具库,提供了类似 Prototype 功能的编程支持,但没有对 JavaScript 内置的对象进行扩展。
    Javascript-279 in Useful JavaScript and jQuery Tools, Libraries, Plugins
    Popcorn.js
    Popcorn.js 是一个HTML5 Video框架,它提供了易于使用的API来同步交互式内容。
    Javascript-315 in Useful JavaScript and jQuery Tools, Libraries, Plugins
    SlickGrid!
    SlickGrid 是一个用于构建简单的、快速、灵活的表格的库。
    Js-004 in Useful JavaScript and jQuery Tools, Libraries, Plugins
    JavaScript InfoVis Toolkit
    The JavaScript InfoVis Toolkit 用于创建交互的可视化数据。
    Javascript-237 in Useful JavaScript and jQuery Tools, Libraries, Plugins
    Handlebars.js: Minimal Templating on Steroids
    Handlebars 是一个 JavaScript 页面模板库,帮助你轻松的构建语义化模板。可参考ThinkVitamin的文章
     Getting Started with Handlebars.js
    Javascript-280 in Useful JavaScript and jQuery Tools, Libraries, Plugins
    Backbone.js
    Backbone.js 是一个 JavaScript MVC 应用框架,通过Models进行key-value绑定及自定义事件处理。
    Javascript-313 in Useful JavaScript and jQuery Tools, Libraries, Plugins
    OpenFaces
    OpenFaces 是一个包含AJAX-powered JSF组件库,一个Ajax框架和一个客户端校验框架的开源框架,它源于QuipuKit并增加了一些新的组件和特性。
    Js-009 in Useful JavaScript and jQuery Tools, Libraries, Plugins
    d3.js
    D3 可以让你绑定任何数据到文档对象模型(DOM),然后再应用数据驱动传递给文档。
    Javascript-238 in Useful JavaScript and jQuery Tools, Libraries, Plugins
    Visual Event JS Library
    Javascript 是事件驱动的语言,这个可视化事件库用于帮助你追踪事件。
    Js-005 in Useful JavaScript and jQuery Tools, Libraries, Plugins
    Tempo: JSON rendering engine
    Tempo 节奏是一个小的JSON渲染引擎,让你使用纯HTML就可以构建数据模板。
    Js-002 in Useful JavaScript and jQuery Tools, Libraries, Plugins
    Art Deco – Selectable Text
    实现字母分离效果的库,保留了文本能被选择的特性。
    Javascript-153 in Useful JavaScript and jQuery Tools, Libraries, Plugins
    Using Less.js to Simplify Your CSS3
    LESS 是一个扩展CSS,让其拥有动态语言特性的库。
    Javascript-175 in Useful JavaScript and jQuery Tools, Libraries, Plugins

    如何判断Javascript对象是否存在

    Javascript语言的设计不够严谨,很多地方一不小心就会出错。

    举例来说,请考虑以下情况。

    现在,我们要判断一个全局对象myObj是否存在,如果不存在,就对它进行声明。用自然语言描述的算法如下:

      if (myObj不存在){

        声明myObj;

      }

    你可能会觉得,写出这段代码很容易。但是实际上,它涉及的语法问题,远比我们想象的复杂。Juriy Zaytsev指出,判断一个Javascript对象是否存在,有超过50种写法。只有对Javascript语言的实现细节非常清楚,才可能分得清它们的区别。

    第一种写法

    根据直觉,你可能觉得可以这样写:

      if (!myObj) {

        myObj = { };

      }

    但是,运行这段代码,浏览器会直接抛出ReferenceError错误,导致运行中断。请问错在哪里?

    对了,if语句判断myObj是否为空时,这个变量还不存在,所以才会报错。改成下面这样,就能正确运行了。

      if (!myObj) {

        var myObj = { };

      }

    为什么加了一个var以后,就不报错了?难道这种情况下,if语句做判断时,myObj就已经存在了吗?

    要回答这个问题,就必须知道Javascript解释器的工作方式。Javascript语言是"先解析,后运行",解析时就已经完成了变量声明,所以上面的代码实际等同于:

      var myObj;

      if (!myObj) {

        var myObj = { };

      }

    因此,if语句做判断时,myObj确实已经存在了,所以就不报错了。这就是var命令的"代码提升"(hoisting)作用。Javascript解释器,只"提升"var命令定义的变量,对不使用var命令、直接赋值的变量不起作用,这就是为什么不加var会报错的原因。

    第二种写法

    除了var命令,还可以有另一种改写,也能得到正确的结果:

      if (!window.myObj) {

        myObj = { };

      }

    window是javascript的顶层对象,所有的全局变量都是它的属性。所以,判断myobj是否为空,等同于判断window对象是否有myobj属性,这样就可以避免因为myObj没有定义而出现ReferenceError错误。不过,从代码的规范性考虑,最好还是对第二行加上var:

      if (!window.myObj) {

        var myObj = { };

      }

    或者写成这样:

      if (!window.myObj) {

        window.myObj = { };

      }

    第三种写法

    上面这种写法的缺点在于,在某些运行环境中(比如V8、Rhino),window未必是顶层对象。所以,考虑改写成:

      if (!this.myObj) {

        this.myObj = { };

      }

    在全局变量的层面中,this关键字总是指向顶层变量,所以就可以独立于不同的运行环境。

    第四种写法

    但是,上面这样写可读性较差,而且this的指向是可变的,容易出错,所以进一步改写:

      var global = this;

      if (!global.myObj) {

        global.myObj = { };

      }

    用自定义变量global表示顶层对象,就清楚多了。

    第五种写法

    还可以使用typeof运算符,判断myObj是否有定义。

      if (typeof myObj == "undefined") {

        var myObj = { };

      }

    这是目前使用最广泛的判断javascript对象是否存在的方法。

    第六种写法

    由于在已定义、但未赋值的情况下,myObj的值直接等于undefined,所以上面的写法可以简化:

      if (myObj == undefined) {

        var myObj = { };

      }

    这里有两个地方需要注意,首先第二行的var关键字不能少,否则会出现ReferenceError错误,其次undefined不能加单引号或双引号,因为这里比较的是undefined这种数据类型,而不是"undefined"这个字符串。

    第七种写法

    上面的写法在"精确比较"(===)的情况下,依然成立:

      if (myObj === undefined) {

        var myObj = { };

      }

    第八种写法

    根据javascript的语言设计,undefined == null,所以比较myObj是否等于null,也能得到正确结果:

      if (myObj == null) {

        var myObj = { };

      }

    不过,虽然运行结果正确,但是从语义上看,这种判断方法是错的,应该避免。因为null指的是已经赋值为null的空对象,即这个对象实际上是有值的,而undefined指的是不存在或没有赋值的对象。因此,这里只能使用"比较运算符"(==),如果这里使用"精确比较运算符"(===),就会出错。

    第九种写法

    还可以使用in运算符,判断myObj是否为顶层对象的一个属性:

      if (!('myObj' in window)) {

        window.myObj = { };

      }

    第十种写法

    最后,使用hasOwnProperty方法,判断myObj是否为顶层对象的一个属性:

      if (!this.hasOwnProperty('myObj')) {

        this.myObj = { };

      }

    总结

    1. 如果只判断对象是否存在,推荐使用第五种写法。

    2. 如果除了对象是否存在,还要判断对象是否有null值,推荐使用第一种写法。

    3. 除非特殊情况,所有变量都应该使用var命令声明。

    4. 为了跨平台,建议避免使用window表示顶层对象。

    5. 在Javascript语言中,null和undefined容易产生混淆。在可能同时涉及两者的情况下,建议使用"精确比较"运算符(===)。

    Linux系统信息查看命令大全


    Linux系统信息查看命令大全

    系统
    # uname -a               # 查看内核/操作系统/CPU信息
    # head -n 1 /etc/issue   # 查看操作系统版本
    # cat /proc/cpuinfo      # 查看CPU信息
    # hostname               # 查看计算机名
    # lspci -tv              # 列出所有PCI设备
    # lsusb -tv              # 列出所有USB设备
    # lsmod                  # 列出加载的内核模块
    # env                    # 查看环境变量
    资源
    # free -m                # 查看内存使用量和交换区使用量
    # df -h                  # 查看各分区使用情况
    # du -sh <目录名>        # 查看指定目录的大小
    # grep MemTotal /proc/meminfo   # 查看内存总量
    # grep MemFree /proc/meminfo    # 查看空闲内存量
    # uptime                 # 查看系统运行时间、用户数、负载
    # cat /proc/loadavg      # 查看系统负载
    磁盘和分区
    # mount | column -t      # 查看挂接的分区状态
    # fdisk -l               # 查看所有分区
    # swapon -s              # 查看所有交换分区
    # hdparm -i /dev/hda     # 查看磁盘参数(仅适用于IDE设备)
    # dmesg | grep IDE       # 查看启动时IDE设备检测状况
    网络
    # ifconfig               # 查看所有网络接口的属性
    # iptables -L            # 查看防火墙设置
    # route -n               # 查看路由表
    # netstat -lntp          # 查看所有监听端口
    # netstat -antp          # 查看所有已经建立的连接
    # netstat -s             # 查看网络统计信息
    进程
    # ps -ef                 # 查看所有进程
    # top                    # 实时显示进程状态
    用户
    # w                      # 查看活动用户
    # id <用户名>            # 查看指定用户信息
    # last                   # 查看用户登录日志
    # cut -d: -f1 /etc/passwd   # 查看系统所有用户
    # cut -d: -f1 /etc/group    # 查看系统所有组
    # crontab -l             # 查看当前用户的计划任务
    服务
    # chkconfig --list       # 列出所有系统服务
    # chkconfig --list | grep on    # 列出所有启动的系统服务
    程序
    # rpm -qa                # 查看所有安装的软件包