http://www.cnblogs.com/hongru/archive/2010/09/24/1833928.html
中秋最后一天假期,还是憋屈在家里,没事可做,发发关于两个看似很基础却又很有意义的两个问题的一点感想,如题...
一.对象深拷贝:
对应的浅拷贝,对象是通过地址指向来获得引用的,所以单纯的用一个新对象指向源对象就是浅拷贝,对新对象的操作同样会影响的源对象。好比小明有个U盘,里面装有一些资料,一天,小红也需要这个U盘里的资料,于是拿过来改了里面的资料,结果小明再用时,里面资料就变了,因为两个人用的其实是同一个u盘嘛... 如下:
1
2
3
4
5
|
var
obj = {a:
'a'
};
var
obj1 = obj;
obj.a =
'a1'
;
alert(obj.a);
alert(obj1.a);
|
运行
那么怎么样才能资料各自私有而不影响对方呢,显而易见嘛,让小红也去买个u盘,并把资料也拷一份到她的u盘里,各用个的就行了。于是:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
function
clone(myObj)
{
if
(
typeof
(myObj) !=
'object'
|| myObj ==
null
)
return
myObj;
var
myNewObj =
new
Object();
for
(
var
i
in
myObj) myNewObj[i] = clone(myObj[i]);
//递归调用,当对象中又有对象时
return
myNewObj;
}
var
obj = {a:
'a'
};
var
obj1 = obj;
var
obj2 = clone(obj);
obj.a =
'a1'
;
alert(obj.a);
alert(obj1.a);
alert(obj2.a);
|
运行
至此,区别也很明显了,obj1浅拷贝由于是访的同一个对象,故改变源对象obj,新对象obj1也随之改变。而深拷贝obj2是新建了一个对象实例,与源对象obj互不干扰。
二.关于数组去重
网上很流行一种解法,如下:
1
2
3
4
5
6
7
8
9
10
|
Array.prototype.filter =
function
(){
for
(
var
i=0,temp={},result=[],ci;ci=
this
[i++];){
if
(temp[ci])
continue
;
temp[ci]=1;
result.push(ci);
}
return
result;
}
var
aa=[
'1'
,
'2'
,
'3'
,
'1'
,
'2'
];
alert(aa.filter());
|
运行
它其实是用了对象的特性,把每个数组元素当做一个对象的属性来判断是否存在,这样做有个好处是不用二次遍历数组。然而,乍一看结果没问题,可是一旦数组里有了number,布尔值,对象等作为元素的时候,就会发现问题了。
原因在于:对象则要求其属性值必须为字符串,如果提供给对象的属性不是字符串,那么则会自动调用 toString 方法转化为字符串形式,于是,严格来讲,这种方法只能在数组元素全为字符串时才成立
我们再看看jquery的源码是怎么实现数组去重的方法的:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
unique:
function
( array ) {
var
ret = [], done = {};
try
{
for
(
var
i = 0, length = array.length; i < length; i++ ) {
var
id = jQuery.data( array[ i ] );
if
( !done[ id ] ) {
done[ id ] =
true
;
ret.push( array[ i ] );
}
}
}
catch
( e ) {
ret = array;
}
return
ret;
},
|
乍一看,其实思路跟我上面说的方法是一样的,可是别忘了很重要的一点,var id = jQuery.data( array[ i ] );这一句,其实是把每个数组元素都转换成了节点数组再做的判断。
所以,如果把安全性放在首位,效率次之的话,数组去重还是应该老老实实二次遍历数组,如下:
1
2
3
4
5
6
7
8
9
10
11
12
|
function undulpicate(array){
for ( var i=0;i<array.length;i++) {
for ( var j=i+1;j<array.length;j++) {
//注意 ===
if (array[i]===array[j]) {
array.splice(j,1);
j--;
}
}
}
return array;
}
|
当然,如果能确定数组元素类型,大可不必这样做,毕竟二次遍历在数据量大的时候是个不小的消耗。。
此外,貌似hash查找可以减少一次遍历...具体还没想过...唉,今天就到此位置吧