(js基础篇)7.对象(包含对象的拷贝,手写深拷贝)

127 阅读4分钟

说明:对象用来存储键值对和更复杂的实体,对象中的一个属性就是一个键值对("key:value"),其中key是一个字符串(也叫做属性名),值(value)可以是任何值。

1.创建语法

let obj = new Object(); // "构造函数"的语法
let user = {}; // "字面量"的语法

2.文本和属性

说明:我们可以在创建对象的时候,立即将一些属性以键值对的形式放到{...}中。

let user = {
  name: "mamba",
  age: 25
};
  • 属性有键,位于冒号":"的前面,值在冒号的右边。
  • 读取属性 user.name user.age
  • 添加属性 user.isAdmin = true;
  • 移除属性 delete user.age;
  • PS:用const声明的对象能被修改。

3.方括号

说明:对于多词属性,点操作不能使用。

let user = {
  name: "mamba",
  age: 25
};
// 设置
user["likes birds"] = true;
// 读取
console.log(user["likes birds"]);
// 删除
delete user["likes birds"];

4.计算属性

说明:当创建一个对象时,我们可以在对象字面量中使用方括号。这叫做计算属性。

let name = "age";
let obj = {
  [name]: 25
}
console.log(obj); // { age: 25 }
let obj2 = {
  [name + 'More']: 30
}
console.log(obj2); // {ageMore: 30}

PS:方括号比点符号更强大。它允许任何属性名和变量,但写起来也更加麻烦

5.属性值简写

let name = "mamba";
let age = 25;
let obj = {
	name, age, status: 1
}
// 等价于
let obj = {
	name: name,
    age: age,
    status: 1
}

6.属性名称限制

说明:属性命名没有限制。可以是任何字符串或者symbol,其他类型会被自动地转换为字符串。

7.属性存在性测试,"in"操作符

说明:js对象,属性不存在读取不到的时候也不会报错,会返回undefined。

  • 直接调用属性看是否存在

      let user = {};
      console.log(user.name === undefined); // true
    
  • 通过操作符"in"

      let user = {
        name: 'Mamba',
        age: 25
      };
      console.log("name" in user); // true
      console.log("height" in user); // false
    

8."for...in"循环

说明:为了遍历一个对象的所有键(key),可以使用一个特殊形式的循环:for..in

  • 语法:

      for (key in object) {
          // 对此对象属性中的每个键执行的代码
      }
    
  • 代码案例

      let user = {
        name: 'Mamba',
        age: 25
      };
      for (let key in user) {
        console.log(key + '----' + user[key]);
      }
      // 打印结果
      // name----Mamba
      // age----25
    

9.对象拷贝

说明:对象与原始类型其中一个基本的区别是:对象“通过引用的形式”被存储和拷贝。

  • 分析

      let user = {
        name: 'Mamba'
      };
      let admin = user;
      admin.name = 'job';
      console.log(user.name); // job
    

'案例图' PS:user变量获取的是{name:'xxx'}的地址,admin等于user之后获取的也是指向的地址,从admin修改name的值,user通过地址获取的name值就是admin修改之后的值。

10.通过引用来比较

说明:对于对象来说,普通相等==和严格相等===是两个作用结果完全一样的运算符。

  • 仅当两个对象为同一对象时,两者才相等

      let user = {
      name: 'Mamba'
    };
    let admin = user;
    console.log(admin == user); // true
    console.log(admin === user); // true
    
  • 两个独立的对象不管怎么样都不相等,即时他们的值一模一样

      let user = {
      name: 'Mamba'
    };
    let admin = {
      name: 'Mamba'
    };
    console.log(admin == user); // false
    console.log(admin === user); // false
    

11.对象的克隆与合并,Object.assign

说明:当我们遇到这一个需求,我们需要复制一个对象,和之前获得相同对象的引用完全不同,是独立的拷贝。

  • for循环进行拷贝

      let user = {
      name: 'Mamba',
      age: 30,
      desc: '我很厉害'
    };
    let clone = {};
    for(let key in user){
      clone[key] = user[key]
    }
    console.log(clone);
    // {name: "Mamba",age: 30,desc: "我很厉害"}
    
  • Object.assign方法来达成同样的效果

参数说明 Object.assign(dest, [src1, src2, src3...])
第一个参数 dest是指目标对象。
更后面的参数 src1, ..., srcN (可按需传递多个参数)是源对象
该方法将所有源对象的属性拷贝到目标对象 dest
调用结果返回 dest

let user = {
  name: 'Mamba',
  age: 30,
  desc: '我很厉害'
};
let newUser = {};
Object.assign(newUser, user);
console.log(newUser);
// 结果 {name: 'Mamba', age: 30, desc: '我很厉害'}

12.手写深拷贝

  • 法一:JSON.stringify和JSON.parse配合。最简单:)

  • 法二:

      let obj1 = {
      	name: 'mamba',
      	age: 50,
      	child: {
      		name: 'm-james',
      		age: 26,
      		child: {
      			name: 'j-wisdom',
      			age: 3
      		}
      	}
    
      }
    
      var deepCopy = function(obj) {
      	// 判断是否是对象
      	if (typeof obj !== 'object') return;
      	var newObj = obj instanceof Array ? [] : {};
      	for (var key in obj) {
    
      	    // 判断是否有下级
      	    if (obj.hasOwnProperty(key)) {
      	    	// 判断属性值的类型,如果是对象则递归调用
      	    	newObj[key] = typeof obj[key] === 'object' ? deepCopy(obj[key]) : obj[key];
    
      	    }
    
      	}
    
      	return newObj;
    
      }
      var obj2 = deepCopy(obj1);
      console.log(obj2);