克隆
克隆和我们前面所讲的继承有一些区别,克隆是复制出来一个一模一样的目标对象,而克隆又分为浅层克隆和深层克隆,本质就是把一个对象的一些属性复制成完全一样的另一个对象。
浅度克隆
浅度克隆是认为对象的的属性,没有对象和数组,直接把对象的一些属性给复制过来。
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);
这种方法可以直接调用。