深入理解JavaScript对象创建

简介: 深入理解JavaScript对象创建

深入理解JavaScript对象创建

在JavaScript中,对象是包含相关数据和方法的集合。这些数据和方法可以是任何数据类型,包括其他对象。JavaScript提供了多种创建对象的方式,每种方式都有其独特的用途和优点。本文将详细解析JavaScript中创建对象的各种方法,并讨论它们的适用场景。

1. 对象字面量

对象字面量(也称为对象初始化器)是创建对象的最简单方式。只需要定义一个变量,并使用大括号 {} 包围属性和方法即可。

let person = {
    name: "Alice",
    age: 30,
    greet: function() {
        console.log(`Hello, my name is ${this.name}`);
    }
};

这种方式非常直观,并且代码量很少。但是,如果你需要创建多个具有相同属性和方法的对象,这种方式就会变得冗余。

另外补充,下面方式是等价的,都是创建了一个原型为Object.prototype的空对象

let a = {}//字面量的方式创建
let a = new Object()//Object构造函数创建
let a = Object.creat(Object.prototype)
let b = Object.creat(null)

这是创建一个原型为null的空对象

Object.create(proto,[propertiesObject])方法创建一个新对象,使用现有的对象来提供新创建的对象的__proto__。

proto 新创建对象的原型对象; propertiesObject 可选:

  1. configurable true
    只有该属性描述符的类型可以被改变并且该属性可以从对应对象中删除。 默认为 false
  2. enumerable true
    只有在枚举相应对象上的属性时该属性显现。 默认为 false
  3. value 与属性关联的值。可以是任何有效的JavaScript值(数字,对象,函数等)。 默认为undefined.
  4. writable true
    只有与该属性相关联的值被assignment operator改变时。 默认为 false
  5. get 作为该属性的 getter 函数,如果没有 getter 则为undefined。函数返回值将被用作属性的值。 默认为 undefined
  6. set 作为属性的 setter 函数,如果没有 setter 则为undefined。函数将仅接受参数赋值给该属性的新值。默认为 undefined
let o = Object.create({}, { p: { value: 42, writable: true } })
o.p = 2
console.log(o.p);//2

举个例子这个o对象就是一个原型是{},属性p可写的一个对象;

2. 构造函数

构造函数是一种特殊的函数,用于初始化新创建的对象。在JavaScript中,你可以使用 new 关键字和构造函数来创建对象。

function Person(name, age) {
    this.name = name;
    this.age = age;
    this.greet = function() {
        console.log(`Hello, my name is ${this.name}`);
    };
}

let alice = new Person("Alice", 30);
let bob = new Person("Bob", 25);

这种方式解决了对象字面量方式的冗余问题,但每个对象仍然有其自己的 greet 方法,这在一定程度上还是浪费了内存。

3. 原型

在JavaScript中,每个函数都有一个 prototype 属性,它是一个指向原型对象的指针。原型对象包含可以由特定类型的所有实例共享的属性和方法。

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

Person.prototype.greet = function() {
    console.log(`Hello, my name is ${this.name}`);
};

let alice = new Person("Alice", 30);
let bob = new Person("Bob", 25);

在这个例子中,greet 方法被定义在 Person 的原型上,因此所有的 Person 实例都可以访问这个方法,但这个方法只在内存中存在一次,从而节省了内存。

4. Object.create()

Object.create() 方法创建一个新对象,使用现有的对象作为新创建对象的 __proto__

let personProto = {
    greet: function() {
        console.log(`Hello, my name is ${this.name}`);
    }
};

let alice = Object.create(personProto);
alice.name = "Alice";
alice.age = 30;

let bob = Object.create(personProto);
bob.name = "Bob";
bob.age = 25;

Object.create()` 提供了更多的灵活性,因为它允许你选择一个原型对象,而不是使用构造函数的原型。然而,这种方式通常不用于创建具有复杂结构的对象。


5. class(ES6 引入)

从 ES6 开始,JavaScript 引入了 class 关键字,作为创建对象和继承的新方式。尽管 class 本质上仍然是基于原型的继承,但它提供了一种更清晰、更直观的语法。

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

    greet() {
        console.log(`Hello, my name is ${this.name}`);
    }
}

let alice = new Person("Alice", 30);
let bob = new Person("Bob", 25);

class` 语法使代码更易于理解和组织,特别是对于那些熟悉基于类的面向对象编程的开发者来说。

再看另外一个例子

  class Person {
    //私有属性和私有方法,方法是在属性名之前,使用#表示
    //只能在类的内部使用(this.#count)。如果在类的外部使用,就会报错。
      #count = 0;
      //ES6 明确规定,Class 内部只有静态方法,没有静态属性(在提案中)
      static bar() {
        console.log(`静态方法`);
      }
        constructor(name, age, job) {
            this.name = name;
            this.age = age;
            this.job = job;
            this.eat = function () {
                console.log(`${this.name}调用了eat`);
            }
        }
        //sayName这个方法在实例的prototype上
        sayName() {
            console.log(this.name);
        }
        //sneeze打喷嚏这个方法在实例对象上  赋值语句+箭头函数 创建实例的自定义方法
        sneeze = ()=>{
          console.log(this)
        }
    }

类的属性除非是显式定义在其本身上(即this对象上),否则都定义在原型上。eat,sayName这两个方法是实例都可以调用,区别就是sayName在实例的prototype上。

总结

JavaScript提供了多种创建对象的方式,每种方式都有其优点和适用场景。对象字面量方式简单直观,但不适合创建大量相似对象。构造函数方式解决了对象字面量的冗余问题,但可能会浪费内存。原型方式进一步节省了内存,但需要更多的理解和注意。Object.create() 提供了更多的灵活性,但通常不用于复杂对象。最后,class 语法提供了一种更清晰、更直观的方式来创建对象和进行继承,特别是对于熟悉基于类的编程的开发者来说。

在选择创建对象的方式时,应根据具体需求和场景进行权衡。例如,如果你需要创建大量具有相同属性和方法的对象,那么使用构造函数和原型可能是更好的选择。如果你需要更多的灵活性和控制,那么 Object.create()class 可能是更好的选择。无论选择哪种方式,都应确保代码的可读性和可维护性。

相关文章
|
2月前
|
JavaScript 前端开发
JavaScript Date(日期) 对象
JavaScript Date(日期) 对象
42 2
|
21天前
|
JavaScript 前端开发
如何在 JavaScript 中使用 __proto__ 实现对象的继承?
使用`__proto__`实现对象继承时需要注意原型链的完整性和属性方法的正确继承,避免出现意外的行为和错误。同时,在现代JavaScript中,也可以使用`class`和`extends`关键字来实现更简洁和直观的继承语法,但理解基于`__proto__`的继承方式对于深入理解JavaScript的面向对象编程和原型链机制仍然具有重要意义。
|
25天前
|
Web App开发 JavaScript 前端开发
如何确保 Math 对象的方法在不同的 JavaScript 环境中具有一致的精度?
【10月更文挑战第29天】通过遵循标准和最佳实践、采用固定精度计算、进行全面的测试与验证、避免隐式类型转换以及持续关注和更新等方法,可以在很大程度上确保Math对象的方法在不同的JavaScript环境中具有一致的精度,从而提高代码的可靠性和可移植性。
|
25天前
|
JavaScript 前端开发 图形学
JavaScript 中 Math 对象常用方法
【10月更文挑战第29天】JavaScript中的Math对象提供了丰富多样的数学方法,涵盖了基本数学运算、幂运算、开方、随机数生成、极值获取以及三角函数等多个方面,为各种数学相关的计算和处理提供了强大的支持,是JavaScript编程中不可或缺的一部分。
|
2月前
|
存储 JavaScript 前端开发
JavaScript 对象的概念
JavaScript 对象的概念
38 4
|
2月前
|
缓存 JavaScript 前端开发
JavaScript中数组、对象等循环遍历的常用方法介绍(二)
JavaScript中数组、对象等循环遍历的常用方法介绍(二)
40 1
|
2月前
|
存储 JavaScript 前端开发
js中函数、方法、对象的区别
js中函数、方法、对象的区别
20 2
|
2月前
|
JavaScript 前端开发 Unix
Node.js 全局对象
10月更文挑战第5天
30 2
|
2月前
|
存储 JavaScript 前端开发
js中的对象
js中的对象
20 3
|
2月前
|
JavaScript 前端开发
JavaScript Math(算数) 对象
JavaScript Math(算数) 对象
21 4