Back to prev

Javascript Some Tricks

Jun 30, 2020
Linkang Chan
@Jesse Chan

Json Stringify

Version sort

正常通过字符串比较是不足以应对大部分场景的,因为字符串是通过 unicode 的顺序去排序的。所以会出现如下情况:

> a='5'
'5'
> b='201'
'201'
> a < b
false

所以单纯的字符串比较是不合理的,所以当我们需要比较版本号,普适的方式是循环比较法:

arr.sort((a, b) => {
    let i = 0;
    const arr1 = a.split('.');
    const arr2 = b.split('.');

    while (true) {
        const s1 = arr1[i];
        const s2 = arr2[i++];

        if (s1 === undefined || s2 === undefined) {
            return arr2.length - arr1.length;
        }

        if (s1 === s2) continue;

        return s2 - s1;
    }
});

此外还有一种加权的方式,这种方式适合版本号格式比较固定的情况。当版本的格式不够统一时需要多操作一步。具体代码如下:

const maxLen = Math.max(
    ...arr.map((item)=>item.split('.').length)
);

const reducer = (acc,value,index) => 
    acc+(+value)*Math.pow(p,maxLen-index-1);

const gen = (arr) =>
    arr.split('.').reduce(reducer,0);

arr.sort((a,b)=> gen(a)>gen(b)?-1:1);

console.log(arr)

Array Deep Copy

深拷贝一般是在数组里面的内容是对象的时候使用,可以通过如下的例子来看下区别:

> a = [1,2,3]
[ 1, 2, 3 ]
> b = [...a]
[ 1, 2, 3 ]
> a[1]=5
5
> b
[ 1, 2, 3 ]

可以看到当数组内容是简单类型时,修改源数组的内容,不会对拷贝后的数组产生影响。下面是一个对象拷贝的例子:

> a = [ {k1:1, k2:2}, {k1:2, k2:3} ]
[ { k1: 1, k2: 2 }, { k1: 2, k2: 3 } ]
> b = [...a]
[ { k1: 1, k2: 2 }, { k1: 2, k2: 3 } ]
> a[0].k1=5
5
> b
[ { k1: 5, k2: 2 }, { k1: 2, k2: 3 } ]

可以看到,当修改了 a 中内容后,b 中的内容发生了变化。此时我们需要使用深拷贝来解决这个问题。

> c = a.map(item => { return { ...item} })
[ { k1: 5, k2: 2 }, { k1: 2, k2: 3 } ]
> a
[ { k1: 5, k2: 2 }, { k1: 2, k2: 3 } ]
> a[0].k1=6
6
> c
[ { k1: 5, k2: 2 }, { k1: 2, k2: 3 } ]
>

可以看到此时的 c 并没有因为 a 中的内容发生变化而发生变化。 还有另外一种深拷贝方式,相比较于 map 的方式略慢一些。

> d = JSON.parse(JSON.stringify(a))
[ { k1: 5, k2: 2 }, { k1: 2, k2: 3 } ]
> a
[ { k1: 5, k2: 2 }, { k1: 2, k2: 3 } ]
> a[0].k1=6
6
> d
[ { k1: 5, k2: 2 }, { k1: 2, k2: 3 } ]