js创建对象方式总结

本文介绍了JavaScript中创建对象的几种方式,包括字面量、Object.create()、类、工厂函数、构造函数、原型模式以及寄生构造函数,分析了它们的特点、优缺点和适用场景。
摘要由CSDN通过智能技术生成

js创建对象方式总结

字面量方式

使用大括号 {} 创建一个新对象,这是最简单直接的方式。适用于创建单个对象,可以直接在大括号内定义属性和方法。

    let person = {
      name: 'John',
      age: 30,
      gender: 'male'
    };
    let preson2 = {
      name: 'John',
      age: 30,
      gender: 'male'
    };
    console.log(person === preson2) // false

这种创建方式对于创建大量相似对象的时候,会产生大量的重复代码

Object.create()

Object.create(proto[, propertiesObject]) 方法创建一个新对象,使用现有的对象来提供新创建的对象的__proto__。这个方法允许你选择一个原型对象作为新对象的原型。

    //3.Object.create()
    let personPrototype = {
      introduce: function () {
        console.log(`My name is ${this.name} and I'm ${this.age} years old.`);
      }
    };

    let person = Object.create(personPrototype);
    person.name = 'John';
    person.age = 30;
    console.log(person)// {name: 'John', age: 30}
    console.log(person.__proto__ === personPrototype) // true
    console.log(person.__proto__ === personPrototype.prototype) // false  personPrototype.prototype是undefined
    console.log(personPrototype.__proto__ === Object.prototype) // true

image-20240304151746691

在 JavaScript 中,只有函数对象(Function对象)才有 prototype 属性。函数对象的 prototype 属性是一个对象,用于存储构造函数实例化的对象所共享的属性和方法。

当你使用 new 关键字创建一个函数的实例时,实例的 __proto__ 属性会指向该函数的 prototype 属性。这种机制支持了原型继承,让多个实例能够共享同一个原型对象上的方法和属性。

类(ES6+)

在ES6中引入了类的概念,使用 class 关键字可以定义类,然后通过 new 关键字创建类的实例。类语法是一个语法糖,背后仍然使用原型和构造函数。

    class Person {
      constructor(name, age) {
        this.name = name;
        this.age = age;
      }

      greet() {
        console.log("Hello, " + this.name);
      }
    }

    const person = new Person("Dave", 32);
    console.log(person.__proto__ === Person.prototype) // true

工厂函数

工厂函数是一个普通函数,用来返回一个新的对象。工厂函数不使用 new 关键字,但可以接受参数并根据参数定制返回的对象。

    function createPerson(name, age) {
      var o = new Object();
      o.name = name;
      o.age = age;
      o.greet = function () {
        console.log("Hi, my name is " + this.name + " and I am " + this.age + " years old.");
      };
      return o;
    }

    const person = createPerson("Eve", 27);
    console.log(person.__proto__ === createPerson.prototype) // false
    console.log(person.__proto__ === Object.prototype) // true
    // 无法识别为特定类型
    console.log(person instanceof createPerson) // false
    console.log(person instanceof Object) // true

工厂模式通过一个函数来封装创建对象的细节,从而实现对象创建代码的复用。但是,使用工厂模式创建的对象,无法识别为特定的类型

构造函数

使用 new 关键字和构造函数来创建对象。构造函数通常首字母大写,可以接受参数用于设置对象的初始属性。

   function Person(name, age, gender) {
      this.name = name;
      this.age = age;
      this.gender = gender;
      this.greet = function() {
        console.log("Hi, my name is " + this.name + " and I am " + this.age + " years old.");
      };
    }

    let person = new Person('John', 30, 'male');
    let preson2 = new Person('John', 30, 'male');
    console.log(person === preson2) // false

构造函数模式可以通过new关键字调用,创建的对象与构造函数之间建立了联系,可以通过instanceof来识别对象类型。但每个实例都会创建新的函数实例。

构造函数模式相对于工厂模式的优点是,所创建的对象和构造函数建立起了联系,因此可以通过原型来识别对象的类型。但是构造函数存在一个缺点就是,造成了不必要的函数对象的创建,因为在 js 中函数也是一个对象,因此如果对象属性中如果包含函数的话,那么每次都会新建一个函数对象,浪费了不必要的内存空间,因为函数是所有的实例都可以通用的。

原型模式

原型模式通过构造函数的prototype属性定义共享的属性和方法,解决了构造函数模式中的函数重复创建问题。但所有实例共享属性和方法,对于引用类型的属性可能会导致意外的结果。

    function Person() { }

    Person.prototype.name = "John";
    Person.prototype.age = 30;
    Person.prototype.arr = [1,2,3]
    Person.prototype.greet = function () {
      console.log("Hi, my name is " + this.name + " and I am " + this.age + " years old.");
    };

    var person1 = new Person();
    var person2 = new Person();
    console.log(person1 === person2) // false
    console.log(person1.__proto__ === Person.prototype) // true
    person1.name = "person1"
    console.log(person1.name) // "person1"
    console.log(person2.name) // "John"
    // 存在一个引用类型如 Array 这样的值,那么所有的实例将共享一个对象,一个实例对引用类型值的改变会影响所有的实例。
    person1.arr.push(4) // 
    console.log(person1.arr) // [1, 2, 3, 4]
    console.log(person2.arr) // [1, 2, 3, 4]

构造函数和原型模式的组合

这种模式结合了构造函数模式和原型模式的优点,通过构造函数初始化属性,通过原型共享方法。

    function Person(name, age) {
      this.name = name;
      this.age = age;
    }

    Person.prototype.greet = function () {
      console.log("Hi, my name is " + this.name + " and I am " + this.age + " years old.");
    };

    var person1 = new Person("John", 30);
    var person2 = new Person("Jane", 25);

动态原型模式

动态原型模式在构造函数内部动态定义原型方法,只在第一次调用构造函数时执行,结合了构造函数和原型模式的优点,同时提高了封装性。

function Person(name, age) {
  this.name = name;
  this.age = age;

  if (typeof this.greet != "function") {
    Person.prototype.greet = function() {
      console.log("Hi, my name is " + this.name + " and I am " + this.age + " years old.");
    };
  }
}

var person1 = new Person("John", 30);
var person2 = new Person("Jane", 25);

寄生构造函数模式

寄生构造函数模式类似于工厂模式,但使用new关键字调用。它允许在不修改原构造函数的情况下,对创建的对象进行扩展。与工厂模式一样,创建的对象无法识别为特定的类型。

function Person(name, age) {
  var o = new Object();
  o.name = name;
  o.age = age;
  o.greet = function() {
    console.log("Hi, my name is " + this.name + " and I am " + this.age + " years old.");
  };
  return o;
}

var person1 = new Person("John", 30);
var person2 = new Person("Jane", 25);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱写bug的小邓程序员

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值