1. 数组的细节
来看下面的问题:
var arr = [1,2,3];
console.log(arr[1] != arr['01']);
控制台会返回什么值呢?为什么?以下来自MDN:
Array elements are object properties in the same way that toString is a property, but trying to access an element of an array as follows throws a syntax error, because the property name is not valid:
//虽然数组元素和toString()一样是对象的方法,但尝试如下的访问方式会出现错误,因为属性名不合法。
console.log(arr.0); // a syntax error
There is nothing special about JavaScript arrays and the properties that cause this. JavaScript properties that begin with a digit cannot be referenced with dot notation; and must be accessed using bracket notation. For example, if you had an object with a property named ‘3d’, it can only be referenced using bracket notation. E.g.:
//javascript数组和属性并没有特别之处。以数字开头的属性不能通过点运算符引用,必须使用括号引用。比如:一个有名为“3D”的对象只能通过下列方式引用。*
var years = [1950, 1960, 1970, 1980, 1990, 2000, 2010];
console.log(years.0); // a syntax error
console.log(years[0]); // works properly
renderer.3d.setTexture(model, 'character.png'); // a syntax error
renderer['3d'].setTexture(model, 'character.png'); // works properly
以上的内容说明开篇的问题中arr['01']
的结果应该是undefined
,而arr[1]
括号中的数字会发生如下转化:1=>'1'
。这也就解释了为什么arr[1] != arr['01']的运算结果为true
而arr[1] != arr['1'] 为false
的原因。
2. 数组的方法
concat():The concat() method returns a new array comprised of the array on which it is called joined with the array(s) and/or value(s) provided as arguments.
//返回一个新数组,数组由调用它的数组和作为参数传入的数组或值组成。
如下所示,concat()在传入一个带有返回值立即执行的匿名函数后,会直接将新的数组与原数组合并得到结果。
var arr =[1,3,4];
var result = arr.concat(function (){
var test = ['a','b','c','d'];
return test;
}());
console.log(result); //[ 1, 3, 4, 'a', 'b', 'c', 'd' ]
类似这样的数组方法还有很多,但通过MDN我们可以归纳三类数组方法,分别是:
变换方法(mutator)、访问方法(accessor)、迭代方法(loop)。
如下表:
(*)表示改变原有数组。
mutator(*) | accessor | loop |
---|---|---|
pop | concat | filter |
push | join | forEach |
reverse | indexOf | every |
shift | lastindexOf | map |
sort | slice | some |
splice | toSource | |
unshift | toString | |
valueOf |
善用上表中的方法将会给数据处理带来一些很好的体验。比如some() 和 every() 方法,相当于对所有数组元素做了逻辑或和且判断,并且直接返回布尔值。在某些数据校验中,使用这样的方法,将会省去我们自己声明布尔值的过程,简化代码的同时提高了可读性。虽然在兼容性上,这两个方法只对IE9+支持,但是在MDN中提供了下列扩展可以很好解决这个问题,当然前提是some和every方法在Array.prototype上并不事先存在。
if (!Array.prototype.some)
{
Array.prototype.some = function(fun /*, thisArg */)
{
'use strict';
if (this === void 0 || this === null)
throw new TypeError();
var t = Object(this);
var len = t.length >>> 0;
if (typeof fun !== 'function')
throw new TypeError();
var thisArg = arguments.length >= 2 ? arguments[1] : void 0;
for (var i = 0; i < len; i++)
{
if (i in t && fun.call(thisArg, t[i], i, t))
return true;
}
return false;
};
}
sort()方法和比较函数的运用在具体的运用中也有一些有意思的地方,如下:
var arr = [1,10,2,20,3,30];
arr.sort();
console.log(arr); // [ 1, 10, 2, 20, 3, 30 ]
得到这样的排序结果的原因是:If compareFunction is not supplied, elements are sorted by converting them to strings and comparing strings in Unicode code point order. For example, “Cherry” comes before “banana”. In a numeric sort, 9 comes before 80, but because numbers are converted to strings, “80” comes before “9” in Unicode order. // 如果没有比较函数,被排序的原宿会被转化为字符串根据在万国码位的字符排序。比如:Cherry在banana的前面。在数值排序中9在80的前面,但因为数字会被转化,所以万国码排序中“80”在“9”的前面。
那么比较函数又是什么?比较函数提供一个返回值供sort()方法使用,遵循以下规则:
- If compareFunction(a, b) is less than 0, sort a to a lower index than b, i.e. a comes first.
- If compareFunction(a, b) returns 0, leave a and b unchanged with respect to each other, but sorted with respect to all different elements. Note: the ECMAscript standard does not guarantee this behaviour, and thus not all browsers (e.g. Mozilla versions dating back to at least 2003) respect this.
- If compareFunction(a, b) is greater than 0, sort b to a lower index than a. compareFunction(a, b) must always return the same value when given a specific pair of elements a and b as its two arguments. If inconsistent results are returned then the sort order is undefined.
//
- 如果compareFunction(a,b)返回小于0,那么a的索引就比b小,a应该排在前面。
- 如果compareFunction(a,b)返回0,保留a和b相互不变,但是排序可能遵循不同的元素。注意:ECMAscript标准没有保证这个行为是正常的,因为并不是所有的浏览器都这样(比如:Mozilla的版本号至少在2003)。
- 如果compareFunction(a,b)返回大于0,b的索引就比a小。当一组具体的元素作为两个参数时,compareFunction(a,b)总是返回相同的值。如果不一致的结果返回了,那么排序是未定义的。
var arr = [1,10,2,20,3,30];
arr.sort(function (a,b){
return a - b;
});
console.log(arr); //[ 1, 2, 3, 10, 20, 30 ]
arr.sort(function (a,b){
return b - a;
})
console.log(arr);//[ 30, 20, 10, 3, 2, 1 ]
从上图可以直观的看到,当返回a-b时,升序排列,返回b-a时,降序排列。对此,我总结了一个口诀:“顺着走,大大大”!理解为:当参数顺序和返回式顺序相同时即顺着走,那么结果就是升序排列即大大大!
2015.4.11 晴 公寓