兼容多种模块规范的 javascript 模块化写法

;(function(name,definition){
    
    var hasDefine  = typeof define === 'function',  // 检测上下文环境是否为 AMD 或者 CMD        
        hasExports = typeof module !== 'undefined' && module.exports;  // 检查上下文是否为 node

    if(hasDefine){
        define(definition); // AMD 或者 CMD 环境
    }else if(hasExports){
        module.exports = definition(); // 定义为普通 node 模块
    }else{
        this[name] = definition(); // 将模块的执行结果挂载在 window 变量中,在浏览器中 this 指向 window 变量。
    }

})('hello',function(){ // 此处 hello 只是作为模块化的示例名称
    var hello = function(){};
    return hello;
})

不过此种写法要保证前端引用或者后端使用没有全局的 define 函数覆盖 AMD 或者 CMD 的 define 函数。

此代码来源于 深入浅出Node.js P45 2.7.4,此处为记录以及熟悉。

在经过了IE6 IE7的洗礼之后,我们终于可以放心的使用 inline-block 了,但是在使用 inline-block 的时候,我们总会发现很多莫名其妙的空隙出现在两个 inline-block 元素之间,例如我们的代码如下所示:

<nav>
  <a href="#">One</a>
  <a href="#">Two</a>
  <a href="#">Three</a>
</nav>
nav a {
  display: inline-block;
  padding: 5px;
  background: red;
}

然后在浏览器里面的结果就是:

但是一般情况下,我们这么写,总是想让各个元素紧挨在一起的,如果需要中间有空隙,那我们可以通过 css 来更精确地控制。难道这个是一个 bug。刚刚好可以方便的使用这个属性值了,又出现 bug 了,难道又要骂娘了?

其实,了解了背后的原理,就明白这里其实并不是一个 bug,因为对浏览器来说,回车和换行都会被当做有效地字符,只是看不见而已,由于其被当做有效地字符,所以这个空隙的大小会随着定义的文字大小而改变,所以这里也就是为什么我们不需要它的出现,而要自己控制间隙的原因。那么既然知道了产生这个问题的原意,那就有解决方案来应对它。

方法一,可以通过代码来去掉这个inline-block 元素之间的空格。

<nav>
  <a href="#">
    One</a><a href="#">
    Two</a><a href="#">
    Three</a>
</nav>

或者

<nav>
   <a href="#">One</a
  ><a href="#">Two</a
  ><a href="#">Three</a>
</nav>

或者

<nav>
  <a href="#">One</a><!--
  --><a href="#">Two</a><!--
  --><a href="#">Three</a>
</nav>

然后,这就解决了这个问题,主要就是想办法去掉那个换行或者空格。但是这样子的话,会让我的结构很不好看,尤其是对于处女座的前端来说。

方法二:负边距

nav a {
  display: inline-block;
  margin-right: -4px;
}

此时需要给相应的元素以负边距来抵消产生的空隙,但是上面的原因说过了,由于跟其字体大小有关系,所以在具体的情况下,需要更具字体来调整。风险是,万一用户系统中没有你设定的字体呢?

方法三:不写结束标签

<ul>
  <li>one
  <li>two
  <li>three
</ul>

方法四:字体大小 0

由于空隙来源于字符,那我让他为 0 的大小不就行了?对嘛,真聪明。

nav {
  font-size: 0;
}
nav a {
  font-size: 16px;
}

不过,这样的方式,在某些平台以及某些浏览器上是有 bug 的。而且,如果使用 em 作为单位,那么下面的文字再怎么设置都是 0 了(em相对于父级)。

反正,每种方法都不算优雅,但基本都可以解决问题。

但或者,我们有可能根本就不需要 inline-block ,float 如果好用的话。或者以后可以用 flexbox 了。美好的愿望,在国内。

来源于:Fighting the Space Between Inline Block Elements 按自己的理解翻译,未忠实于原文。

sort 作为数组的方法,被定义在 Array.prototype.sort,也即在 JavaScript 中所有数组都可以使用 sort 方法进行排序。虽然一般情况下,sort 甚至可以不用传递排序函数一样可以正常工作,但很多情况下,我们还是必须明确的定义排序函数,才能更好的按我们的需求来工作,这也是一般情况下建议的方式,因为不知道不同的 js 引擎在不传递排序函数的时候,会按照什么方案进行排序。
例如:

var colors = ['red', 'green', 'blue', 'yellow', 'white'];
console.log(colors.sort());    // ["blue", "green", "red", "white", "yellow"]
console.log(colors);           // ["blue", "green", "red", "white", "yellow"]

如果不传递排序函数,那么,对于字符串来说,其将按照字母顺序来进行排序,可是,如果这些字符串里面有大写小写字母混合呢?

var colors = ['red', 'green', 'blue', 'Yellow', 'White'];
console.log(colors.sort());    // ["White", "Yellow", "blue", "green", "red"]

怎么样,结果不一样了吧?这是因为此时按照 ASCII 编码的顺序进行排序了。

同时,另一个问题是,sort 函数作用于原数组,也即是排序的结果会覆盖排序前的数组。

然后,对于数字数组,不传递排序函数的话,会是什么结果呢?

var money = [12, 3, 7.4, 200];
console.log(money.sort());    // [12, 200, 3, 7.4]

咦?并没有得到预期的结果(除非你的预期不是按数字大小),那么为什么呢?

因为在 sort 排序的时候,如果不传递排序函数,那么会先将所有的元素转换为 字符串 ,然后才会一个字一个字(ASCII,对于 true 或者 false 这类型的值都是一样的)的排序,为什么都转换成字符串,因为 JavaScript 数组中可以是任意类型的数据,所以 JavaScript 无法推断到底转换为什么类型去排序。

那么我们看看不同的数据类型,排序函数的一些写法:

数组内都是数字,或者期望按数字为主的排序方式。

var money = [12, 3, 7.4, 200];
var compare = function(a, b) {return a - b;};
console.log(money.sort(compare)); // [3, 7.4, 12, 200]
//console.log(money.sort(function(a, b) {return a - b;})); // [3, 7.4, 12, 200]

这是最基础的排序函数,任何讲到 JavaScript 排序的地方,基本都会讲这个。首先取前两个元素赋值给 a b,返回 a-b 的值,如果返回负值则 a 在 b 前,等于 0 则无所谓,因为两个元素相等,返回正直,则 a 在 b 后。

对于字符串的元素来说,和数字的差不多,无非就是不同的排序函数,那如果是对象呢?

var people = [
    {
        name: 'Alice',
        id: 1234
    },
    {
        name: 'Bob',
        id: 567
    }
];
var compare = function(a, b) {return a.id - b.id;}
console.log(people.sort(compare)); // Bob is before Alice now

对于元素的排序函数传递的参数都一样,两个数组中的元素,然后此处主要比较两个对象元素的 id 的值,来进行排序的。

可是如果如下面这种情况呢?

var everything = [4, 'Red', '$200', 'white', 7.4, 12, true, 0.3, false];
var compare = function(a, b) {return a - b;};
console.log(everything.sort(compare));

当排序函数进行计算的时候,由于有减法运算的参与,所以这里都会先转成数字进行计算的,但是如果是字符串的话,此处就会转换为 NaN,因为在 ECMA 规范中没有明确定义这时候应该如何进行排序,所以各个平台,也就是各个浏览器(JavaScript环境)的不同,导致最终的结果会不一定相同。大家可以自己在不同的浏览器上测试下。

例子来源:http://zhangwenli.com/blog/2013/11/02/sorting-in-javascript/

一般情况下,我们都使用 JavaScript 的 console.log() 进行 debug 但是,对于 Object 来说,每次 console.log 之后,输出的都是不是十分有好的数据,例如:

var languages = [
    { name: "JavaScript", fileExtension: ".js" },
    { name: "TypeScript", fileExtension: ".ts" },
    { name: "CoffeeScript", fileExtension: ".coffee" }
];

console.log(languages);

输出的就如同下图所示(当然,会根据不同的浏览器以及不同的版本会有所差别):

logging_with_console_log.

然后呢,其实看起来还是那么回事,虽然麻烦点,但是还可以看的清楚,到底什么是什么东西。

再然后呢?如果我们使用这里介绍的 console.table 呢?

不过,聪明的人一眼就看出来其中的玄机了,或者,看到这里,直接就去浏览器的console里面,执行这句代码就完了。怎么样?很好用吧?

不过还是给个例子比较好,因为大部分都比较懒嘛。
还是上边的对象,然后使用 console.table(language) 输出看看。

logging_with_console_table

看到了吧,多么的一目了然!

然后点击各个表头试试看,还可以排序哦。

logging_with_console_table_sorted

好了,上面是数组,但是其实对于对象也是可以使用的哦。

var languages = {
    csharp: { name: "C#", paradigm: "object-oriented" },
    fsharp: { name: "F#", paradigm: "functional" }
};

console.table(languages);

然后看看结果,看到了吧?

logging_with_console_table_object

可是,如果就这么点,那么除了更好的阅读方式之外,就没什么意思。

那么,它还可以过滤,哈哈。

这么:

console.table(languages, ["name", "paradigm"]); //多个 key 组成的数组

或者这么:

console.table(languages, "name”); //单个 key

很多内容来自:http://blog.mariusschulz.com/2013/11/13/advanced-javascript-debugging-with-consoletable