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

克隆

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

浅度克隆

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

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);

这种方法可以直接调用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值