数组排序

利用数组自带的 sort 方法可以实现排序功能(默认升序),例如这样

var arr = [1, 3, 6, 2, 4];
var sortArr = arr.sort(); // [1,2,3,4,6]

如果要降序排序的话,可以这样

var newArr = arr.sort(function (a1, a2) {
return a2 - a1; // 后面大于前面的调换,就是降序排序
});

不仅可以对数字数组排序,还可以对对象数组排序,例如

var arr = [
{ name: 'kobe', age: 40 },
{ name: 'james', age: 36 },
{ name: 'durant', age: 38 },
];
var sortArr = arr.sort(function (a1, a2) {
return a2.age - a1.age;
});
// [{"name":"kobe","age":40},{"name":"durant","age":38},{"name":"james","age":36}]

数组拷贝

常用的数组拷贝有 3 种方法

  • for 循环
  • concat
  • slice

上面 3 个方法可以实现简单的浅拷贝,但是遇到对象数组,每一项会存在单个对象的引用,例如

var arr = [{ name: 1 }, { name: 2 }];
var newArr = arr.slice();
newArr[0].name = 200;
console.log(arr[0].name); // 200
var newArr2 = arr.concat();
newArr2[0].name = 300;
console.log(arr[0].name); // 300

上面修改 newArr 和 newArr2 对象的 name 会影响到原数组的数据,所以需要深拷贝来消除对象的引用

function depCopy(objectToBeCloned) {
// 基本类型
if (!(objectToBeCloned instanceof Object)) {
return objectToBeCloned;
}
var objectClone;
// 判断类型
var Constructor = objectToBeCloned.constructor;
switch (Constructor) {
// 特殊对象
case RegExp:
objectClone = new Constructor(objectToBeCloned);
break;
case Date:
objectClone = new Constructor(objectToBeCloned.getTime());
break;
default:
objectClone = new Constructor();
}
// 克隆属性
for (var prop in objectToBeCloned) {
objectClone[prop] = depCopy(objectToBeCloned[prop]);
}
return objectClone;
}
// 验证代码
var arr = [{ name: 1, hob: [2, 3] }];
var newArr1 = depCopy(arr);
newArr1[0]['hob'][1] = 3000;
console.log(arr[0]['hob'][1]); // 3
arr = [{ name: 1 }, { name: 2 }];
var newArr2 = depCopy(arr);
newArr2[0]['name'] = 2000;
console.log(arr[0]['name']); // 1
arr = [
[1, 3],
[2, 4],
];
var newArr3 = depCopy(arr);
newArr3[0][0] = 1000;
console.log(arr[0][0]); // 1

还有一种更暴力的方法,不过缺点就是数组如果太大,解析时性能会有影响

JSON.parse(JSON.stringify(arr));

新建一个长度为 10000 的 * 字符串

最笨的方法,for 循环,如下

var str = '';
for (var i = 0; i < 10000; i++) {
str += '*';
}

另一种超简单的写法:

var n = new Array(10000).join('*');

少用递归,多用循环

递归和循环大部分情况下是可以互换的,一个经典的例子就是斐波纳契数列,解决方法通常就是用递归来实现,例如这样

function fib(n) {
if (n == 1 || n == 2) {
return 1;
} else {
return fib(n - 1) + fib(n - 2);
}
}

代码是很简单,但是有一个严重的问题就是递归层次太深效率会非常慢,以上可以用循环来解决

function fib2(n) {
if (n == 1 || n == 2) {
return 1;
} else {
var sum = 0,
start = 1,
next = 1,
index = 2;
while (index < n) {
sum = start + next;
start = next;
next = sum;
index++;
}
return sum;
}
}

测试了一下,n = 40 时候效率差距是很大的,时间差距很啊,当 n 更大的时候,递归会导致浏览器卡死

数组的判断

var arr = [];
1. Array.isArray(arr);
2. arr instanceof Array
3. arr.constructor === Array // null不适用
4. var toString = Object.prototype.toString;
toString.call(arr) === '[object Array]'

最后一个可以判断所有数据类型,兼容性高

数组最大和最小值

var numbers = [1, 4, -2, 42, 11, -33];
var max = Math.max.apply(Math, numbers);
var min = Math.min.apply(Math, numbers);