JS 创建对象

ECMA-262 将对象定义为一组属性的无序集合。严格来说,这意味着对象就是一组没有特定顺序的值。对象的每个属性或方法都由一个名称来标识,这个名称映射到一个值。

在 JavaScript 中,有多种方式可以创建对象,每种方式都有其优缺点。以下是几种常用的方法,以及它们的优缺点和示例:

1. 工厂函数

可以复用对象模板 ,没法使用instanceof判断对象类型。

function createPerson(name, age) {
  let o = new Object();
  o.name = name;
  o.age = age;
  o.say = function () {
    console.log(this.name);
  };
  return o;
}
let person1 = createPerson('simahe', 18);
let person2 = createPerson('mingqina', 20);
console.log(person1); //{name: 'simahe', age: 18, say: ƒ}
console.log(person2); //{name: 'mingqina', age: 20, say: ƒ}
console.log(person1 instanceof createPerson); //false
console.log(person1 instanceof Object); //true

2. 字面量方式

语法简洁明了易于理解,但对象模板不能复用。

const person1 = {
  name: 'simahe',
  age: '18',
  say: function () {
    console.log(`name: ${this.name}, age: ${this.age}`);
  },
};
person1.say(); // name: simahe, age: 18
console.log(person1); //{name: 'simahe', age: '18', say: ƒ}
console.log(person1.__proto__ == Object.prototype); //true

3. 构造函数

可以复用对象模板 ,每个实例都会重复创建相同的方法,占用内存。

function Person(name, age) {
  this.name = name;
  this.age = age;
  this.say = function () {
    console.log(this.name);
  };
}
let person1 = new Person('simahe', 18);
let person2 = new Person('mingqian', 20);
console.log(person1); //{name: 'simahe', age: 18, say: ƒ}
console.log(person2); //{name: 'mingqina', age: 20, say: ƒ}
console.log(person1 instanceof Object); //true
console.log(person1 instanceof Person); //true
console.log(person2 instanceof Person); //true

console.log(Person.prototype); //{}空对象,没有定义方法
console.log(person1.__proto__ === Person.prototype); //true
console.log(person1.__proto__.constructor === Person); //true

4.原型模式

函数的属性和方法都定义在 prototype 原型对象上,属性共享问题。

  • PersonPrototype属性,指向它的原型对象;

  • Person.prototype.constructor === Person原型对象的constructor 指向自己;

  • person1,person2,有__proto__属性,指向它的原型对象,也就是构造函数的原型对象;

  • person1.__proto__ === Person.prototypePerson.prototype.__proto__ === Object.prototypeObject.prototype.__proto__ ===null 原型链

    注意:对象是__proto__,函数是prototype

function Person() {}
Person.prototype.name = 'simahe';
Person.prototype.age = 18;
Person.prototype.skill = ['java', 'c#', 'php'];
Person.prototype.say = function () {
  console.log(this.name);
};

let person1 = new Person();
let person2 = new Person();
person1.skill.push('node');
person1.skill.push('go');
console.log(person1.skill); //  ['java', 'c#', 'php', 'node', 'go']
console.log(person2.skill); // 也被修改 ['java', 'c#', 'php', 'node', 'go']
console.log(person1 instanceof Person); //true
console.log(Person.prototype); //{name: 'simahe', age: 18, skill: Array(5), say: ƒ}
console.log(person1.__proto__); //{name: 'simahe', age: 18, skill: Array(5), say: ƒ}
console.log(person2.__proto__); //{name: 'simahe', age: 18, skill: Array(5), say: ƒ}
console.log(person1.__proto__ === Person.prototype); // true
console.log(Person.prototype.__proto__ === Object.prototype); // true
console.log(Person.prototype.constructor === Person);

5. Object.create()

使用现有的对象来提供新创建的对象的 __proto__。性能不如字面量方式。

const personPrototype = {
  name: 'simahe',
  age: '18',
  say: function () {
    console.log(`name: ${this.name}, age: ${this.age}`);
  },
};

const person1 = Object.create(personPrototype);
const person2 = Object.create(personPrototype);
console.log(person1.__proto__); //{name: 'simahe', age: 18, say: ƒ}
console.log(person2.__proto__); //{name: 'mingqina', age: 20, say: ƒ}

6. Class

ES6 新增语法,更适合面向对象语言。

class Parent {
  constructor(name) {
    this.name = name;
  }

  say() {
    console.log(`name: ${this.name}, age: ${this.age}`);
  }
}
class Child extends Parent {
  constructor(name, age) {
    super(name); // 调用父类构造函数
    this.age = age;
  }
}
const child = new Child('simahe', 18);
child.say(); // name: simahe, age: 18
console.log(child.age); // 18

总结

选择对象的创建方式时,考虑代码的可读性、可维护性以及扩展性是非常重要的。

  • 简单对象:字面量方式、工厂函数
  • 多个实例,构造函数、Class
  • 需要继承:Object.create()Class
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值