面向对象基础知识点汇总(1)

135 阅读4分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第3天,点击查看活动详情

一、认识对象

对象(Object)是“键值对”集合,表示属性和值的映射关系。

var obj = {
  name: 'zhangsan',
  age: 18,
  sex: '男',
  'favorite-fruit': '西瓜'
}
  • 以{}包括,每组k:v之间用逗号分隔,最后一组k:v可以不加逗号
  • 若属性名不符合JS命名规范,那么需要用引号包裹,如'favorite-fruit'

二、属性相关操作

2-1、属性的访问

可以使用“点语法”来访问属性:

obj.name
obj.age
obj.sex

若属性名不符合JS命名规范,那么必须使用方括号写法来访问:

obj['favorite-fruit']

若属性名以变量的方式进行存储,也要通过方括号写法进行访问:

var obj = {
  a: 1,
  b: 2,
  c: 3
}
var key = 'c'
console.log(obj[key])

2-2、属性的修改

直接使用赋值运算符直接对某属性进行赋值即可

var obj = {
  a: 1,
  b: 2,
  c: 3
}
obj.a = 5
obj.b ++

2-3、属性的创建

如果对象本身没有该属性,直接通过点语法为该属性赋值即可创建该属性

var obj = {
  a: 1,
  b: 2,
  c: 3
}
obj.d = 8

2-4、属性的删除

如果要删除某个属性,需要使用delete操作符

var obj = {
  a: 1,
  b: 2,
  c: 3
}
delete obj.a

三、对象的方法

如果某个属性值是函数,则它也被成为对象的“方法”:

var obj = {
  name: 'zhangsan',
  age: 18,
  sex: '男',
  'favorite-fruit': '西瓜',
  sayHello: function() {
    console.log('你好')
  }
}
  • 使用“点语法”可对方法进行调用:
obj.sayHello()

四、对象的遍历

与遍历数组类似,对象也可以被遍历,遍历对象使用for...in...循环

  • 使用for...in...循环可遍历出对象的每个键
for(var k in obj) {
  console.log('key: ' + k + 'value: ' + obj[k])
}

五、对象的浅克隆与对象深克隆

5-1、基本类型值与引用类型值

举例当var a = b变量传值时当用==比较时
基本类型值数字、字符串、布尔、undefined、null内存中产生新的副本比较值是否相等
引用类型值对象、数组等内存中不产生新的副本,而是让新变量指向同一个对象比较内存地址是否相同,即比较是否为同一个对象

由于对象是引用类型值,这就意味着:

不能够使用var obj2 = obj1这样的语法克隆一个对象,这会使得obj1的地址值赋值给obj2,使得obj2与obj1指向同一片堆内存区域

  • 使用==或者===进行对象的比较时,比较的是他们是否为内存中的同一个对象,而不是比较值是否相同
var obj1 = {
    a: 1,
    b: 2,
    c: 3
};
var obj2 = {
    a: 1,
    b: 2,
    c: 3
};
console.log(obj1 == obj2);      // false
console.log(obj1 === obj2);     // false

console.log({} == {});          // false
console.log({} === {});         // false

var obj3 = {
    a: 10
};
var obj4 = obj3; // obj4与obj3指向同一个对象,而不是对obj3进行克隆
obj3.a ++;
console.log(obj4); // {a: 11}

5-2、对象的浅克隆

对象的浅克隆即:只克隆对象的“表层”,如果对象的某些属性值又是引用类型值,则不进行进一步克隆,只是传递它们的引用。

  • 使用for...in...可实现对象的浅克隆
var obj1 = {
    a: 1,
    b: 2,
    c: [1,2,3,4,5]
};

// 实现浅克隆
var obj2 = {};
for (var k in obj1) {
    obj2[k] = obj1[k];
}

// 为什么叫浅克隆呢?比如c属性的值是引用类型值,那么本质上obj1和obj2的c属性是内存中的同一个数组,并没有被克隆分开。
obj1.c.push(6);
console.log(obj2);                  // obj2的c中也会多了数字6
console.log(obj1.c == obj2.c);      // true,true就证明了数组是同一个对象

5-3、对象的深克隆

对象的深克隆即克隆对象的全貌,无论其属性值是否又为引用类型,都进行克隆。

  • 需要使用递归进行克隆
var obj1 = {
    a: 1,
    b: 2,
    c: [11, 22, {
        m: 33,
        n: 44,
        p: [55, 66]
    }]
};

// 深克隆
function deepClone(o) {
  // 要判断o是对象还是数组
  if (Array.isArray(o)) {
      // 数组
      var result = [];
      for (var i = 0; i < o.length; i++) {
          result.push(deepClone(o[i]));
      }
  } else if (typeof o == 'object') {
      // 对象
      var result = {};
      for (var k in o) {
          result[k] = deepClone(o[k]);
      }
  } else {
      // 基本类型值
      var result = o;
  }
  return result;
}


var obj2 = deepClone(obj1);
console.log(obj2);

console.log(obj1.c == obj2.c);// false

obj1.c.push(77);
console.log(obj2); // obj2不变,因为实现了深克隆,obj1中的c与obj2中的c是两个完全不同的数组

obj1.c[2].p.push(88);
console.log(obj2);// obj2不变的,实现深克隆后,obj1中c[2]的p数组与obj2中的c[2]的p数组是两个完全不同的数组

要注意,由于typeof 数组的结果也为'object',所以要先通过Array.isArray来判断一下该引用类型值是否为数组,再去判断该引用类型值是否为对象。