您的位置:首页 > Web前端 > JavaScript

js(八)---克隆与数组去重

2017-12-27 15:21 225 查看
克隆

克隆和我们前面所讲的继承有一些区别,克隆是复制出来一个一模一样的目标对象,而克隆又分为浅层克隆和深层克隆,本质就是把一个对象的一些属性复制成完全一样的另一个对象。

浅度克隆

浅度克隆是认为对象的的属性,没有对象和数组,直接把对象的一些属性给复制过来。

function clone(P,C){
var C = C || {};//当没有传值是,默认为一个对象。
for(var prop in P){
if(P.hasOwnProperty(prop)){
C[prop] = P[prop];
}

}
}
var obj1 = {
name : "si",
age : 18,
sex : 'male',
arr : [1,2,3,4]
}
var obj2 = {};
clone(obj1,obj2)
obj1.arr.push(5)
obj1.name = "yun";
console.log(obj2);


打印的结果如下:



我们可以发现,克隆出来的目标对象和本来的源对象之间没有关系了。

但是,当我们有一个属性是引用值(数组或者对象)的时候,按照我们这种克隆方式,只是把这个引用值的指向赋给了新的目标对象,也就是说,我们一旦改变了源对象或者目标对象的引用值属性,另一个也会跟着改变,这一点就是浅层克隆的缺点。

浅度克隆

为了解决浅层克隆的引用值的问题,我们又需要一种深层克隆。

其实深层克隆的原理也很简单,我们只要不克隆引用值的引用,而是吧引用值也当做一个源对象,把里面的值一个一个的克隆进目标对象里面,不就解决了他们二者相同指向的问题了吗。

function deepClone(parent,child){
var child = child || {};
for(var prop in parent){
if(typeof parent[prop] == "object"){
child[prop] = (Object.prototype.toString.call(parent[prop]) === "[object Array]")?[]:{};
deepClone(parent[prop],child[prop]);
}
else{
child[prop] = parent[prop]
}
}
}
var obj1 = {
name: "si",
age: "18",
arr: [1,2,3,4]
}
var obj2 = {}
deepClone(obj1,obj2)
obj1.arr.push(5);
console.log(obj2)




数组去重

第一种方式

这个去重的思路是,现将数组进行排序(sort()),排完之后,前后指定有一样的。然后在拿一个数组保存第一个数,然后在把后面的与它前一个数比较,如果是不相同的,那么进把它保存在数组里面,最后循环结束之后。再将其返回出来,这个方法最好写在数组的原型链上。

Array.prototype.unique = function(){
this.sort();
console.time('第一种时间');
var arr = [this[0]];
for(var i = 1;i < this.length;i++){
if(this[i] !== arr[arr.length - 1]){
arr.push(this[i])
}
}
console.timeEnd('第一种时间');
return arr
}


这种方式虽然比较快,但是它是优缺点的,这个方法改变原数组的位置。如果题目要求不让改变数组的原位置,这种方式就不好使。

这里特说明一下吧,
sort()
这种排序的方式,不是按照大小的方式,它是按照二进制码进行排序的。

var arr1 = [10,2,2,2,4,9,5,3,9,4,3,7,5];
console.log(arr1.sort());//10,2, 2, 2, 3, 3, 4, 4, 5, 5, 7, 9, 9,


想要进行排序也是行的:

arr1.sort(function (a,b){
return a-b;
})


第二种方式

1.构建一个新的数组存放结果。2.for循环中每次从原数组中取出一个元素,用这个元素循环与结果数组对比。3.若结果数组中没有该元素,则存到结果数组中。

Array.prototype.unique = function(){
var arr = [this[0]];
console.time('第二种时间');
for(var i = 1;i<this.length;i++){
var flag = false;
for(var j = 0;j < arr.length;j++){
if(this[i] == arr[j]){
flag = true;
brack;
}
if(!flag){
arr.push(this[i])
}
}
}
console.timeEnd('第二种时间');

return arr;
}


这种方式相对来说是比较慢的,它是经历了两个循环的,用专业术语来讲,它的时间复杂度是(n^2)。这也是很常规的方式,缺点就是循环相对来说比较慢。但是跟第一种方式来比较的话,他不会改变原数组的位置。

第三种方式

这相对来说是比较完善的了,运行的速度比较快,所以这个方式是最常用的的数组去重的方式。

利用的方法是对象属性的唯一性:至于如何对比,就是每次从原数组中取出一个元素,然后到对象中去访问这个属性,如果能访问到值,则说明重复。

Array.prototype.unique = function(){
var arr = [],
obj = {};
console.time('第三种时间');
for(var i = 0;i < this.length; i++){
if(!obj[this[i]]){
obj[this[i]] = 123;
arr.push(this[i])
}
}
console.timeEnd('第三种时间');

return arr;

}


最后说一种方法,es6中的一种去重的方法:

var arr = new Set(arr1);


这种方法可以直接调用。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息