javaScript| 对象的拷贝

 javaScript| 对象的拷贝

上一遍是我们基本素组的拷贝,当然少不了我们对象的拷贝,当然也有我们的浅拷贝和我们的深拷贝滴啦;

然后,深拷贝,从某个角度来说就是我们对象的继承;

     对象拷贝分为浅拷贝(shallow)和深拷贝(deep)两种。浅拷贝只复制一层对象的属性,并不会进行递归复制,而javascript存储对象都是存地址的,所以浅拷贝会导致对象中的子对象指向同一块内存地址;而深拷贝则不同,它不仅将原对象的各个属性逐个复制出去,而且将原对象各个属性所包含的对象也依次采用深拷贝的方法递归复制到新对象上

先补充一点基础知识,然后我们再:

ECMAScript将对象的属性分为两种:数据属性访问器属性。每一种属性内部都有一些特性,这里我们只关注对象属性的[[Enumerable]]特征,它表示是否通过 for-in 循环返回属性,也可以理解为:是否可枚举。

然后根据具体的上下文环境的不同,我们又可以将属性分为:原型属性实例属性。原型属性是定义在对象的原型(prototype)中的属性,而实例属性一方面来自己构造函数中,然后就是构造函数实例化后添加的新属性。

先来复习个方法;

Object.getOwnPropertyNames 返回一个数组,该数组对元素是 obj 自身拥有的枚举或不可枚举属性名称字符串。 数组中枚举属性的顺序与通过 for...in 循环(或 Object.keys)迭代该对象属性时一致。 数组中不可枚举属性的顺序未定义。

for in,Object.keys(),Object.getPropertyNames(),for  其实这几个方法之间的差异主要在属性是否可可枚举,是来自原型,还是实例

方法适用范围描述
for..in 数组,对象 获取可枚举的实例和原型属性名
Object.keys() 数组,对象 返回可枚举的实例属性名组成的数组
Object.getPropertyNames() 数组,对象 返回除原型属性以外的所有属性(包括不可枚举的属性)名组成的数组
for..of 可迭代对象(Array, Map, Set, arguments等) 返回属性值

//先来说说for in 的基本用法; 如上,它是这样定义的:获取可枚举的实例和原型的属性名;

看我们的操作demo 源码:

//第一枚举对象上的属性;

var obj={a:'fuck',b:'the',c:'life'};

for(var property in obj){
  console.log("property:"+property+" value:"+obj[property]);
}

//如果原型上有加个方法;照样能够读取出来;
obj.__proto__.showName="sucker";
for(var property in obj){
  console.log("property:"+property+" value:"+obj[property]);
}

//如果我们为了安全,指向获取它自身的方法;

var hasOwn=Object.prototype.hasOwnProperty;
for(let property in obj){
    if(hasOwn.call(obj,property)){
       console.log("property:"+property+" value:"+obj[property]);
    }
}

// 如果我们给obj加上一个不可枚举的对象,那么他就无法被for in 枚举出来,所以for in object 唯一的限制,就是我们
// 的是否可枚举的属性;

Object.defineProperty(obj,"shit",{
  enumerable:false,   //设置为false,那么就无法通过for in 循环枚举出来;
  value:'shit'
})

for(var property in obj){
    console.log("property:"+property+" value:"+obj[property]);
}

这里在bb一句。对稀疏的数组;它是不会枚举出,空的值(undefined的)

  var arr=[1,,,,,,,,4];
  for(let i=0;i<arr.length;i++){
     console.log(i+"--"+arr[i]);
  }
  for(let property in arr){
    console.log(property); //0 8
  }

然后是我们的object.Keys();

定义:用于获取对象自身所有的可枚举的属性值; 看清楚;对象自身的, 可枚举的;

也就是说不包含原型的属性;后返回一个由属性名组成的数组,对返回的是数组;

自身:

var  langue=["life","fuck","shit"];
console.log(Object.keys(langue));
//["0", "1", "2"]

这个就获取不到(原型上的)

var  langue=["life","fuck","shit"]; //这个数组的值
langue.__proto__.example="msq";   //数组某个角度来说也是对象;这样的做法是添加 属性
console.log(Object.keys(langue)); //["0", "1", "2"]
console.log(langue.example);      //msq

这个也获取不到滴哦

var  langue=["life","fuck","shit"]; //这个数组的值
Object.defineProperty(langue,"example",{
   enumerable:false,
   value:"shit"
})
console.log(Object.keys(langue)); //["0", "1", "2"]
console.log(langue.example);      //shit

Object.getPropertyNames()

从名字上,你就可以知道基本的意思:返回的是对象自身的属性;管尼玛的是否可以枚举,反正就是获取自身的,不会获取原型链上的东西;

哎,日尼玛,又在下雨,老子没心情看老...................这太尼玛多的知识点老,算了再咬咬牙,吃完这篇就回去吃屎~

function person(name,age){
         this.name=name;
         this.age=age;
         this.fn=function (){

         }
}

//原型的方法;
person.prototype.fuck=function (){

}

var p=new person('jack',12);

p.newFun=function (){

}

p['addFun']=function(){
  
}

//定义的不可枚举的属性;
Object.defineProperty(p,'definedFun',{
   enumerable:false,
   value:function (){}
})


var result=Object.getOwnPropertyNames(p)
console.log(result); //["name", "age", "fn", "newFun", "addFun", "definedFun"]

for..of为ES6新增的方法,主要来遍历可迭代的对象(包括Array, Map, Set, arguments等),它主要用来获取对象的属性值,而for..in主要获取对象的属性名。

var colors = ['red', 'green', 'blue'];
colors.length = 5;
colors.push('yellow');

for (var i in colors) {
  // console.log(colors[i]); // red green blue yellow
   console.log(i); // 0125
}

for (var j of colors) {
  console.log(j); // red green blue undefined undefined yellow
}

也可以使用....

var colors = ['red', 'green', 'blue'];
colors.foo = 'hello';

Object.keys(colors).forEach(function(elem, index) {
  console.log(colors[elem]); // red green blue hello
  console.log(colors[index]); // red green blue undefined
});

colors.forEach(function(elem, index) {
  console.log(elem); // red green blue
  console.log(index); // 0 1 2
})


参考文献:http://www.cnblogs.com/wujie520303/p/4931384.html 

原文地址:https://www.cnblogs.com/mc67/p/6938225.html