JavaScript 对象创建的几种方式
工厂模式,构造函数,原型模式,动态原型等

Javascript 创建对象的方式

最近看了一些面试题, 发现自己写了一年多的 js 白写了 😂,只是创建对象的几种方式都不知道。搜集了一些资料汇总一下。

工厂模式

function Person() {
  var o = new Object();
  o.name = "xiao wang";
  o.say = function() {
    alert(this.name);
  };
  return o;
}
var person1 = Person();

Pros:

  • 完成了返回一个对象的要求。

Cons:

  • 无法通过构造方法识别对象,以为都是来自 Object,无法得知是来自 Person。
  • 每次通过 Person 创建对象的时候,所有的 say 方法都是一样的,代码冗余,也存储了多次。

构造函数模式

function Person() {
  this.name = "xiao wang";
  this.say = function() {
    alert(this.name);
  };
}
var person1 = new Person();

Pros:

  • 通过构造方法或者 instanceof 可以识别对象实例的类型。
  • 可以通过 new 关键词来创建对象,更接近 OO 语言中创建对象实例的方式。

Cons: 多个实例的 say 方法都是实现同样的效果,却被存储多次,代码冗余。

原型模式

function Person() {}
Person.prototype.name = "mr wang";
Person.prototype.say = function() {
  alert(this.name);
};
Person.prototype.friends = ["mr li"];
var person1 = new Person();

Pros:

  • say 方法可以共享了,所有实例的 say 方法都指向同一个。
  • 可以动态的添加原型对象上的方法和属性,并直接反映在对象实例上。

Cons:

  • 所有对象实例共享引用类型变量。(指向同一块内存区域)
  • 第一次调用 say 方法或者 name 属性的时候会搜索两次。第一次从实例上寻找 say 方法,然后去原型上去找 say 方法,找到后才会在实例上添加这些方法 or 属性。
  • 所有的方法都是共享的,没有办法创建实例自己的属性和方法,也没有办法像构造函数那样传参。

组合使用构造函数模式和原型模式

function Person(name) {
  this.name = name;
  this.friends = ["mr li"];
}
Person.prototype.say = function() {
  console.log(this.name);
};
var person1 = new Person("mr wang");
person1.say();

Pros:

  • 解决了原型对象对于应用对象的缺点。
  • 解决了原型模式没有办法传递参数的缺点。
  • 解决了构造函数模式不能共享方法的缺点。

动态原型模式

function Person(name) {
  this.name = name;
  if (typeof this.say != "function") {
    Person.prototype.say = function() {
      alert(this.name);
    };
  }
}

Pros:

  • 可以在初次调用构造函数的时候就完成原型对象的修改。
  • 修改能体现在所有的实例中。

寄生构造函数模式

function Person(name) {
  var o = new Object();
  o.name = name;
  o.say = function() {
    alert(this.name);
  };
  return o;
}
var person1 = new Person("mr wang");

Pros:

  • 与工厂方法几乎一样,只是可以通过传参确定变量值。

Cons:

  • 同工厂模式。

稳妥构造函数模式

function Person(name, job) {
  var o = new Object();
  o.say = function() {
    console.log(name);
    console.log(job);
  };
  return o;
}
var person1 = Person("mr wang", "coder");
person1.say(); // "mr wang", "coder"
person1.name; // undefined;
person1.job; // undefined;

Pros:

  • 不向外暴露内部变量,只能通过 say 方法去访问。

Cons:

  • 无法通过 instanceof 来判断实例类型。

Last modified on 2020-02-11