JavaScript中的对象、原型、深浅拷贝

一、JavaScript中对象

1、对象的创建和访问

(1)直接创建

这种方式是直接给定对象的属性和值,用一个变量接收,这个变量指向的就是此对象,只能创建单个对象。

      // (1)直接创建一个对象
      var person = {
        name: "John",
        age: 30,
        occupation: "Engineer",
        // 添加一个方法
        sayHello: function () {
          console.log("Hello, my name is " + this.name);
        },
      };
      // 访问对象的属性
      console.log(person.name); // 输出: John
      // 修改对象的属性值 并打印
      person.age = 35;
      console.log(person.age);  //打印35
      // 调用对象的方法
      person.sayHello(); // 输出: Hello, my name is John

(2)通过构造函数创建

这种方式是先创建一个构造函数,可以是一类事物的共性特征、行为等,后续通过调用构造函数,传递参数来生成不同的对象。

      // (2)构造函数创建
      function Person(name, age) {
        this.name = name;
        this.age = age;
        this.sayHello = function () {
          console.log("Hello, my name is " + this.name);
        };
      }

      // 使用构造函数创建不同对象
      var person1 = new Person("John", 30);
      var person2 = new Person("Jane", 25);

      // 调用对象的方法 
      person1.sayHello(); // 输出: Hello, my name is John
      person2.sayHello(); // 输出: Hello, my name is Jane
    </script>

二、对象原型、原型链

1、构造函数、原型对象、实例对象三者的关系

(1)构造函数

每个构造函数都有一个内置属性prototype,这个属性表示该构造函数的原型,指向一个对象,该称为对象的原型对象。

(2)原型对象

一般存放的是这个构造函数的共有属性和方法,即该构造函数实例对象能访问到的所有属性、方法。

(3)实例对象

实例对象是通过构造函数生成的对象实例,每一个对象实例中,都含有“__proto__”属性,表示此对象的对象原型,指向的是该实例对象构造函数的原型对象,即本对象拥有的属性、方法所在的位置。

同时,在原型对象prototype和对象实例中,都含有一个constructor属性,指向的是他们所属的构造函数,表明他们是属于哪一个构造函数。

2、原型链

在JavaScript中,对象的继承可以通过原型链来体现。

原型链是一种对象之间的链接关系,每个对象都有一个指向其所属原型的属性“__proto__”。当访问一个对象的属性或方法时,如果该对象本身没有该属性或方法,会沿着原型链向上查找,直到找到该属性或方法或者到达链的末端。

 案例:

子类对象访问父类构造函数原型对象的方法

      function Parent() {
        this.name = "Parent";
      }

      Parent.prototype.sayHello = function () {
        console.log("Hello, " + this.name);
      };

      function Child() {
        Parent.call(this);
        this.name = "Child";
      }

      Child.prototype = Object.create(Parent.prototype);
      Child.prototype.constructor = Child;

      var child = new Child();
      child.sayHello(); // 输出 'Hello, Child'

 三、深浅拷贝

当我们需要复制一个数据对象时,就会涉及到对象的克隆。

如果是简单字面量的数据,可以直接赋值给新变量,因为是简单的值赋值,并不会对原有数据产生影响。

但当我们要复制的对象时引用数据类型的时候,直接赋值的方式就不再适用了,因为引用数据类型赋值给其他变量传递的是该对象的地址,此时两个变量指向的都是该对象的地址,任何一个变量发生改变,另一个变量都会同步变化。

对于引用数据类型的赋值,就不能采用简单赋值的方法了。

1、浅拷贝(只能拷贝单层)

前边说到,引用数据类型的直接赋值拷贝方式,传递的是该对象的地址,那么,在拷贝引用数据类型的时候,我们不采用直接赋值,而是将地址里的值作为副本给到新变量对象不就解决了吗?

浅拷贝的原理就是这样,不采用变量直接赋值,而是传递对象值副本。

      // 使用Object.assign()进行浅拷贝
      var obj1 = { name: "Alice", age: 25 };
      var obj2 = Object.assign({}, obj1);
      obj2.name = "Bob";

      console.log(obj1); // { name: 'Alice', age: 25 }
      console.log(obj2); // { name: 'Bob', age: 25 }

      // 使用展开运算符进行浅拷贝
      var obj1 = { name: "Alice", age: 25 };
      var obj2 = { ...obj1 };
      obj2.name = "Bob";

      console.log(obj1); // { name: 'Alice', age: 25 }
      console.log(obj2); // { name: 'Bob', age: 25 }

2、深拷贝

浅拷贝有一个局限性,就是只能拷贝一层的数据。

当对象的属性中出现了引用数据类型时,浅拷贝的结果就是,引用数据类型属性传递的依旧是一个地址引用,该属性的变化还是会和原对象同步。

因此,浅拷贝只适用于对象不存在引用数据类型属性的情况。

深拷贝是在浅拷贝的基础上,在拷贝每一个属性的时候,都对该属性的数据类型进行了判断,如果是基本数据类型,直接拷贝;如果是引用数据类型,则会创建该类型的对象,对该属性进行递归拷贝,直到拷完最底层。

深拷贝的几种方法:

(1)递归拷贝

      //深拷贝
      function deepClone(obj) {
        // 检查如果是基本类型或者null,则直接返回
        if (typeof obj !== "object" || obj === null) {
          return obj;
        }

        // 创建一个新的对象或数组
        var clone = Array.isArray(obj) ? [] : {};

        // 遍历原对象的属性
        for (var key in obj) {
          if (obj.hasOwnProperty(key)) {
            // 递归调用深拷贝函数
            clone[key] = deepClone(obj[key]);
          }
        }
        return clone;
      }

      let obj = {
        name: "andy",
        age: 18,
        address: ["江苏省", "扬州市", "广陵区"],
      };
      //拷贝多层对象并打印
      let obj1 = deepClone(obj);
      console.log(obj1);

 (2)使用lodash库的cloneDeep方法

      //(2)第三方库方法(需要导包)
      let obj2 = _.cloneDeep(obj);
      console.log(obj2);

(3)JSON.parse(JSON.stringify(obj))

      //(3)JSON.parse(JSON.stringify()) 方法
      var obj3 = JSON.parse(JSON.stringify(obj));
      console.log(obj);

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值