NPM 现在变得越来越流行了,但是很多人可能只是用了其中一小部分的功能,但是 NPM 其实有一大票功能可以用,不信你试试 npm -help 看看。

而本文的主要目的就是介绍 npm version 命令,此命令用来更改项目的版本号。这个版本好就是项目中 package.json 文件中的 version 字段。
一般情况下,都类似于这样一段 json。

{
    "name"           : "npm-version",
    "description"    : "npm version command",
    "version"        : "1.1.1611"
}

怎么用呢?
例如,
你修复了一个 bug,要增加一个最小的版本号,那么

npm version patch

如果想要更新次要版本号的话,那么

npm version minor

更或者,你要更新主版本号的话,那么

npm version major

哈哈哈,是不是不用手动更新这个文件了?

还有一点点

如果你正好用 git 来管理你的项目,那么 npm version 也可以顺便创建一个版本 commit 和 tag 。

钩子

最神奇的事情就是给了我们 pre 和 post 这两个钩子。

即:
在 npm version 执行之前,pre 这个钩子,就会被执行,而在 npm version 执行之后,post 这个钩子也会被执行。
所以呢,如果你想在更新版本号之后在执行一些操作,那么就应该这样写。

"scripts" : {
	"postversion" : "git push && git push --tags"
}

这样子,在更改了版本号之后,就会自动执行这些 git 命令了。
那么想在更新版本号之前呢?咋办啊?

"scripts" : {
	"start" : "node app.js",
	"pretest":"rm -Rf build && gulp build && cd build && npm install --production",
	"test":"./test/run.sh",
	"preversion":"npm test",
	"postversion" : "git push && git push --tags"
}

看,完成了,一个还算基本完成了的 package.json 文件,在改变版本号之前,先测试一下嘛。

如果想看更多的 npm version 的信息,请访问:https://docs.npmjs.com/cli/version

来源:http://blog.js-republic.com/npm-version-is-cool-you-should-use-it/

iscolor 是否是颜色 接受正常的颜色关键字和十六位表示法以及RGB表示法等。
isnumber 是否是数字
isstring 是否是字符串
iskeyword 是否是关键字 这个没搞明白到底用来判断什么东西。
isurl 是否是 url  例如 url(…),貌似必须这样子才行。

ispixel 是否是像素  应该判断给定的值是否是 数字+px 的。
ispercentage 是否是百分比 应该判断给定的值是否是 数字+% 的。
isem 是否是 em
isunit 是否是某个单位的,两个参数 如果待验证的值为指定单位的数字则返回 true

用法:(同时包含了 when 的一种用法)
.mixin (@a) when (isnumber(@a)) {
padding:@a;
}
.x {
.mixin(5);
}
如果 .x 中的 mixin 给的是数字的话,输出:
.x {
padding:5;
}
否则什么都不输出。

面向对象编程

封装

对象生成的原始模式

var Cat = {
    name  : '',
    color : ''
}

然后生成实例对象,

var cat1 = {};

cat1.name = '大毛';
cat1.color = '黄色';

var cat2 = {};

cat2.name = '二毛';
cat2.color = '黑色';

很简单,但问题是,这样生成的“实例对象”其实和原型对象之间基本没有任何联系。而且生成多个实例的时候,没有简洁的方法,会非常麻烦。

原始模式的改进

function Cat(name,color){
    return {
        name  : name,
        color : color
    }
}

然后生成实例对象,但其实就等于在调用函数,返回一个对象。

var cat1 = Cat('大毛','黄色');
var cat2 = Cat('二毛','黑色');

这种问题是,如果 Cat 中不进行额外的处理,这里仍旧不能反映出来 cat1 和 cat2 内在的联系。

构造函数模式

function Cat(name,color){
    this.name = name;
    this.color = color;
}

现在就可以生成实例对象了。

var cat1 = new Cat('大毛','黄色');
var cat2 = new Cat('二毛','黑色');

这时 cat1 和 cat2 会自动含有一个 constructor 属性,指向他们的构造函数。

console.log(cat1 instanceof Cat); //true
console.log(cat2 instanceof Cat); //true

但此时这种方式仍旧存在其固有的问题。假设这里有一个方法。

function Cat(name,color){
    this.name = name;
    this.color = color;
    this.type = '猫科动物';
    this.eat = function(){console.log('吃老鼠');}
}

生成实例

var cat = Cat('大毛','黄色');
console.log(cat.type); // 猫科动物
cat.eat(); // 吃老鼠。

表面上没什么问题,用的时候也很好用,但是假如我们需要生成大量的 Cat 的实例,那么每个实例都会有 type 属性和 eat 方法,而且这两个都是一摸一样的内容,导致了内存的浪费,因为此时两个实例的相同属性和方法,并不是同样的内存地址。会存在多份。

那么,能不能将所有的相同的属性和方法只存在一份,然后每个实例同样的也可以使用呢?答案肯定是可以的。

prototype 模式

function Cat(name,color){
    this.name = name;
    this.color = color;
}

Cat.prototype.type = '猫科动物';
cat.prototype.eat = function(){console.log('吃老鼠');}

这时候,

var cat1 = new Cat('大毛','黄色');
var cat2 = new Cat('二毛','黑色');

此时,再多的实例对象,其 type 属性和 eat 方法都指向的是同一份,也即相同的内存地址。

console.log(cat1.eat === cat2.eat); //true

prototype 模式的验证方法

为了配合 prototype 模式, javascript 定义了一些辅助方法,帮助我们更方便的使用它。

isPrototypeOf()

这个方法用来判断,某个 prototype 对象和某个实例之间的关系。

console.log(Cat.prototype.isPrototypeOf(cat1)); //true

hasOwnProperty()
次方法用来判断某个属性到底是prototype 对象的属性还是类定义的(本地属性)。

console.log(cat1.hasOwnProperty('name')); true
console.log(cat1.hasOwnProperty('type')); false

in 运算符

此运算符用来判断某个属性是不是存在于某个实例中,即某个实例是否包含某个属性,不管是本地还是继承自 prototype

console.log("name" in cat1); // true
console.log('type' in cat1); // true
console.log('typo' in cat1); // false

in 运算符还可以用来遍历对象的属性。

for(var key in cat1){
    console.log('cat1[' + key ' ]=' + cat1[key]);
}

当然在遍历的时候可以使用 hasOwnProperty() 来限制输出的属性。

var getCursorPositionOfPage = function(e){
    var x, y;
 
    e = e || window.event;
 
    x = e.pageX || (e.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft));
    y = e.pageY || (e.clientY + (document.documentElement.scrollTop  || document.body.scrollTop));
 
    return {
        'x':x,
        'y':y
    };
};

使用方式:

document.querySelector("body").addEventListener("click",getCursorPositionOfPage ,false);

document.getElementsByTagName("body")[0].onmousemove = getCursorPositionOfPage ;

经过简单的测试,各个浏览器的差异如下:

 pageY       chrome/IE10/IE9/firefox29          随滚动条滚动而变化        页面高度   X 同理      IE8/IE7 未定义

 clientY     chrome/IE10/IE9/IE8/IE7/firefox29  不随滚动条滚动而产生变化   窗口高度   X 同理



 document.documentElement   chrome/IE10/IE9/IE8/IE7/firefox29     html

 document.body              chrome/IE10/IE9/IE8/IE7/firefox29     body
// 滚动条未滚动
 document.documentElement.scrollTop    chrome            0

 document.body.scrollTop               chrome            0

// 滚动条滚动
 document.documentElement.scrollTop    chrome            0

 document.body.scrollTop               chrome            100


// 滚动条未滚动
 document.documentElement.scrollTop    IE10/IE9/IE8/IE7/firefox29            0

 document.body.scrollTop               IE10/IE9/IE8/IE7/firefox29            0

// 滚动条滚动
 document.documentElement.scrollTop    IE10/IE9/IE8/IE7/firefox29            100

 document.body.scrollTop               IE10/IE9/IE8/IE7/firefox29            0

上面的 0 表示就是 0 ,100 表示有值。

兼容多种模块规范的 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,此处为记录以及熟悉。

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/