介绍

Array.sort([compareFunction])

对Array里面的元素进行升序排序

关于排序的规则

默认的排序

如果compareFunction没有提供的时候,默认把所有Array里面的元素转换为字符串,然后取第一个字符,比较它们的Unicode值,进行正序排序。

这个转为字符串再比较第一个字符的Unicode值,很关键,很多数字的比较,经常就是这样出错的。


[1,2,3].sort();  // ==> [1,2,3]  正确

[9, 80].sort();  // ==> [9, 80]  错误

[9, 80].sort();  // ==> [80, 9]  正确

上面例子中,数组[9, 80]进行sort的时候,先转为为字符串 “9”, “80”, 再比较第一个字符, “9”和”8″

根据这个比较结果进行排序,所以最后80会在9前面,而不是按照它们的数值大小进行排序的。

想自行测试的,可以看看这个demo(http://www.icondownloader.com/demo/sort-stable.html]

compareFunction的排序

进行sort的时候,如果compareFunction提供了,会往compareFunction传两个数组的元素(类似compareFunction(a, b))

取compareFunction的返回值,如果小于0,则表明a小于b;大于0,则a大于b

最后对结果进行升序排序,如果a小于b,则[a, b]; 如果a大于b 则[b, a]

这里有个技巧,在排序的时候,如果想实现降序排序,可以在compareFuction里面实现类似:return !(a-b);

sort stable

关于排序,有个stable的说法,也就是,排序完成之后,对于值相同的元素,在排序结束之后,能否保留其在排序之前的顺序。

sort stable

具体的概念可以参考维基百科https://en.wikipedia.org/wiki/Sorting_algorithm#Stability

目前的主流浏览器对stable的sort的支持情况如下:

Browser Sort is stable Sort is unstable
Firefox 8 all lengths
Safari 5.1.1 all lengths
Opera 11.52 all lengths
Internet Explorer 6, 7, 8 all lengths
Internet Explorer 9 all lengths
Android 2.3 Browser all lengths
Chrome 15 .. 17.0.942.0 length <= 10 length > 10

可以参考此网站,检测浏览器的sort情况http://ofb.net/~sethml/is-sort-stable.html

sort的效率

可以尝试着对compare function在执行的时候,进行一个计数。这样可以知道每次sort,总共执行了多少次compare function。

我这边写了个demo,有兴趣的可以在自己本机的各个浏览器上测试看看。http://www.icondownloader.com/demo/sort-compare-function-call-times.html

这边我贴出我自己Mac OSX Yosemite 10.10.4下的浏览器的运行结果

## chrome 版本 42.0.2311.135 (64-bit)
Array length is: 5 and sort call compare 7 times;
Array length is: 10 and sort call compare 23 times;
Array length is: 11 and sort call compare 22 times;
Array length is: 12 and sort call compare 19 times;
Array length is: 13 and sort call compare 27 times;
Array length is: 14 and sort call compare 25 times;
Array length is: 15 and sort call compare 24 times;
Array length is: 20 and sort call compare 29 times;
Array length is: 50 and sort call compare 80 times;
Array length is: 100 and sort call compare 206 times;
Array length is: 1000 and sort call compare 1996 times;
Array length is: 10000 and sort call compare 20206 times;

## Safari 版本 8.0.7 (10600.7.7)
Array length is: 5 and sort call compare 8 times;
Array length is: 10 and sort call compare 23 times;
Array length is: 11 and sort call compare 28 times;
Array length is: 12 and sort call compare 31 times;
Array length is: 13 and sort call compare 35 times;
Array length is: 14 and sort call compare 40 times;
Array length is: 15 and sort call compare 44 times;
Array length is: 20 and sort call compare 65 times;
Array length is: 50 and sort call compare 232 times;
Array length is: 100 and sort call compare 568 times;
Array length is: 1000 and sort call compare 8996 times;
Array length is: 10000 and sort call compare 123583 times;

## Firefox (Developer Edition) 40.0a2 (2015-05-29)
Array length is: 5 and sort call compare 6 times;
Array length is: 10 and sort call compare 26 times;
Array length is: 11 and sort call compare 24 times;
Array length is: 12 and sort call compare 33 times;
Array length is: 13 and sort call compare 48 times;
Array length is: 14 and sort call compare 48 times;
Array length is: 15 and sort call compare 37 times;
Array length is: 20 and sort call compare 70 times;
Array length is: 50 and sort call compare 245 times;
Array length is: 100 and sort call compare 574 times;
Array length is: 1000 and sort call compare 8600 times;
Array length is: 10000 and sort call compare 114046 times;

从上面的数据可以看出两个结论:

  1. chrome的执行效率明显高于Safari和Firefox。但是chrome的sort是unstable的,而Safari和Firefox是stable的。是不是可以认为,因为chrome不需要考虑stable,所以提高了执行效率。

  2. 可以看出随着数组长度的增加,比较的次数是指数增加的

用map来提高提高sort的性能

从上面的结论2可以知道,在数组长度很长的时候,compareFunction的调用次数是很多的,这个时候,提高compareFunction的效率就很有必要性了。

现在咱们构建一个数组

var arr = [],
    arrLen = 1000,
    i = 0;

function makeWord(){
    var word = [],
        words = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'],
        wordsLength = words.length,
        arrMinLen = 3,
        arrLen = arrMinLen + Math.floor( Math.random()*9 ),

        i = 0;

    for (i = 0; i < arrLen; i++){
        word.push( words[Math.floor( Math.random()*wordsLength )] );
    }

    return word.join('');
}

for (i = 0; i < arrLen; i++) {
    arr.push( makeWord() );
}

然后比较一下它们小写字母状态下的排序

// 未优化
arr.sort(function(a, b){
    return +(a.toLowerCase() > b.toLowerCase()) || +(a.toLowerCase() === b.toLowerCase())-1;
});

// 优化后

// 用一个临时数组来保存位置和计算后的数值
var mapped = list.map(function(el, i) {
  return { index: i, value: el.toLowerCase() };
})

// 排序这个已经计算后的临时数组
mapped.sort(function(a, b) {
  return +(a.value > b.value) || +(a.value === b.value) - 1;
});

// 根据位置信息 对应映射生成一个排序后的数组
var result = mapped.map(function(el){
  return list[el.index];
});
// 不支持map的时候的兼容方法

var tmpArr = [],
    result = [],
    i = 0,
    len = arr.length;

for (i = 0; i < len; i++) {
    tmpArr[i] = {index: i, value: arr[i].toLowerCase()};
}

tmpArr.sort(function(a, b) {
  return +(a.value > b.value) || +(a.value === b.value) - 1;
});

for (i = 0; i < len; i++) {
    result[i] = arr[tmpArr[i].index];
}

具体的执行效果可以看看jsperf里面的这个地址http://jsperf.com/arraysortperform

参考文章:
+ https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort
+ https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Grammar_and_types#Unicode
+ https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#String_literals
+ http://ofb.net/~sethml/is-sort-stable.html
+ http://stackoverflow.com/questions/3026281/array-sort-sorting-stability-in-different-browsers

本文参考自:Git-与其他系统-迁移到-Git

也建议阅读之前,先看看此文章,本文主要是对里面方法的一个补充和完善,保证可用性

第一步:把之前svn的提交者的信息映射为git需要的

在本地的svn目录,执行以下命令:

svn log ^/ --xml | grep "^<author" | sort -u | perl -pe 's/<author>(.*?)</author>/$1 = /' > users.txt

显而易见,本方法要求主机上安装了grep,sort 和 perl.

最后得到的user.txt 是所有svn提交者的name。

在对应等号后面加上Email地址。

最终变成如下格式:

schacon = Scott Chacon 
selse = Someo Nelse 

第二步:使用svn2git来导入

在一个新的打算放置导入成功之后的git项目的目录(最后也把上一步的users.txt拷贝到此处)

前往github上面的svn2git项目,安装这个工具,能比较方便的进行svn到git的导入

执行以下命令:

svn2git svn://yourdomain.com/your/path/to/svn --username xingwang --verbose --authors users.txt

解释一下几个参数:
--username: 设定你在svn里面的用户名,方便执行svn co
--verbose: debug模式,能够了解svn2git执行了哪些命令,方便出问题的时候调试
--authors: 用来设定提交者信息,也就是上一步生成的users.txt

这份读书笔记是看了阮一峰的《React 入门实例教程》之后撰写的,留作记录。需要看原文的可以点击前面的书名访问对应链接。

这篇文章的目的

  • 介绍react
  • 如何下载react
  • 如何安装react
  • 如何使用react

文章的组织架构

从易到难的开始介绍。

react在页面的部署

  1. 依赖的两个js
  2. jsx 模板的标签规范
  3. 模板的编译应该放到服务器完成

模板语法

  1. React.render() 转换模板为HTML并插入节点
  2. 允许HTML和javascript混写。
    1. 规则是:遇到HTML标签(以<开头)则视为HTML,遇到代码块(以{)开头,视为javascript
    2. HTML内容可以直接写在javascript变量里
    3. javascript变量可以直接插入到模板。如果变量是数组,则自动展开这个数组的所有成员

组件

组件介绍

  1. 用React.createClass来生成组件类
  2. createClass的传参对象,需要一个render方法,用来描述组件的渲染
  3. 组件类以大驼峰方式书写
  4. 组件类以模板的方式调用,写法可以有单标签和双标签两种
  5. 组件类以模板的方式调用,实际是实例化了产生了一个对象,以下简称为组件
  6. 组件的调用和HTML标签完全一致,能加入属性。属性的调用,可以通过组件类的实例在javascript中,以this.props.xxx的方式调用
  7. 组件的style属性设定的时候,期望的值是一个对象{opacity: 0.5, marginLeft: ‘1px’} 而不是一个字符串,最终的写法是{{opacity: 0.5, marginLeft: ‘1px’}} 外面一对大括号表明是javascript代码块,里面的一对大括号,表明是对象
  8. 冲突的属性名class和for 要对应改为className和htmlFor,因为class和for是javascript的保留字
  9. this.props的属性和组件HTML属性一一对应,但是this.props.children例外,它表示组件的子节点
  10. 在用双标签的方式调用组件的时候,标签之间的HTML即为组件的子节点,完全和原生HTML一致

组件的特性

  1. findDOMNode
    1. virtual DOM
    2. virtual DOM 通过 DOM diff算法映射到真实DOM上
    3. findDOMNode用于获取跟组件关联的真实DOM的节点
    4. 只有在virtual DOM插入文档之后才能起作用
  2. this.state
    1. 类似状态机的概念
    2. getInitialState方法来设定初始状态
    3. 通过用户互动修改状态,一般是对应的event function来setState
    4. render里面,根据不同的状态渲染出不同的UI
    5. setState自动调用render重绘UI
    6. 区分this.props和this.state: this.props类似常量,设定之后不改变;this.state是随着用户互动而变化的特性
    7. 表单内容的变化也是通过state来进行更新的

组件生命周期

  1. 三个状态
    1. Mounting 已插入真实DOM
    2. Updating 正在被重新渲染
    3. Unmounting 已移出真实DOM
  2. 每个状态提供两个回调函数,will在进入状态之前调用,did在进入状态之后调用
  3. 三个状态共计五种回调函数,书写方式component是前缀,will/did是行为,Mount/Update/Unmount是状态
    1. componentWillMount()
    2. componentDidMount()
    3. componentWillUpdate(object nextProps, object nextState)
    4. componentDidUpdate(object prevProps, object prevState)
    5. componentWillUnmount()   为什么没有componentDidUnmount() ?
  4. 特殊状态的回调
    1. componentWillReceiveProps(object nextProps) 已加载组件收到新参数
    2. shouldComponentUpdate(object nextProps, object nextState) 组件判断是否重新渲染时调用 不明白

结合其他库或者框架使用

  1. react没有任何依赖
  2. react只关注表现层
  3. 如果希望对组件的DOM进行操作,尽量在componentDidMount中进行,保证真实DOM已经存在

主旨

React是一个关注表现层,以组件来构建内容,以状态机来完成交互的UI改变的,可以在浏览器端和服务器端同时运行的前端框架。