创建对象的几种方法及优缺点

传统方式

直接通过构造函数创建一个新对象。

var obj = new Object();
//等同于 var obj = {}
1
2

使用字面量的方式更简单,其实他俩是一样的。 优点是足够简单,缺点是每个对象都是独立的。

工厂模式

function createObj(name, age) {
  var obj = {};
  obj.name = name;
  obj.age = age;
  return obj;
}
var Anson = createObj("Anson", 18);
console.log(Anson);
//{name: "Anson", age: 18}
1
2
3
4
5
6
7
8
9

优点是 可以解决创建多个相似对象的问题,缺点是 无法识别对象的类型。

构造函数

function Person(name, age) {
  this.name = name;
  this.age = age;
  this.sayName = function() {
    alert(this.name);
  };
}
var person = new Person("小明", 13);
console.log(person);
//Person {name: "小明", age: 13, sayName: ƒ}
1
2
3
4
5
6
7
8
9
10

优点是 可以创建特定类型的对象,缺点是 多个实例重复创建方法

(构造函数+原型)组合模式

function Person(name, age) {
  this.name = name;
  this.age = age;
  Person.prototype.sayName = function() {
    alert(this.name);
  };
}
var person = new Person("小白", 18);
console.log(person);
//Person {name: "小白", age: 18} __proto__ -> sayName: ƒ ()
1
2
3
4
5
6
7
8
9
10

优点 多个实例引用一个原型上的方法 比较常用

动态原型

function Person(name, age) {
  this.name = name;
  this.age = age;
  if (typeof this.sayName != "function") {
    Person.prototype.sayName = function() {
      alert(this.name);
    };
  }
}
var person = new Person("小红", 15);
console.log(person);
//Person {name: "小红", age: 15} 动态创建sayName: ƒ ()
1
2
3
4
5
6
7
8
9
10
11
12

优点 可以判断某个方法是否有效,来决定是否需要初始化原型,if 只会在仅在碰到第一个实例调用方法 时会执行,此后所有实例共享此方法,需要注意的一点是,不能重新原型对象。

寄生构造函数模式

function Person(name, age, job) {
  var o = new Object();
  o.name = name;
  o.age = age;
  o.job = job;
  o.sayName = function() {
    console.log(this.name);
  };
  return o;
}
var friend = new Person("her", 18, "Front-end Engineer");
friend.sayName();
//her
1
2
3
4
5
6
7
8
9
10
11
12
13

除了使用new操作符,其他的和工厂函数一样,可以为对象创建构造函数。

稳妥模式

function Person(name, age){
    var o={};
    o.sayName=function(){ alert(name) }
    return o;
}
var person = ('小亮'24);
person.sayName();//’小亮‘
1
2
3
4
5
6
7

除了使用person.sayName()之外 ,没有办法在访问到 name 的值,适合在某些安全执行环景下使用。

Object.create()

const person = {
  isHuman: false,
  printIntroduction: function() {
    console.log(`My name is ${this.name}. Am I human? ${this.isHuman}`);
  },
};

const me = Object.create(person);

me.name = "Matthew"; // "name" is a property set on "me", but not on "person"
me.isHuman = true; // inherited properties can be overwritten

me.printIntroduction();
// expected output: "My name is Matthew. Am I human? true"
1
2
3
4
5
6
7
8
9
10
11
12
13
14

传入一个原型对象,创建一个新对象,使用现有的对象来提供新创建的对象的proto,实现继承。

参考: