js实用小技巧

数组排序

利用数组自带的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);