js创建对象的几种模式

一、工厂模式

顾名思义,就是像工厂一样的生成对象,在函数中定义好对象的属性和方法,然后在调用该函数传入参数赋值给定义好的属性,就能生成一个新的对象。

function createPerson(name, age, job) {

  var o = new Object();

  o.name = name;

  o.age = age;

  o.job = job;

  o.sayName = function () {

    alert(this.name);

  };

  return o;

}

var person1 = createPerson("Nike", 29, "teacher");

var person2 = createPerson("Arvin", 20, "student");

工厂函数的缺点:没有解决对象识别的问题(不知道这个对象的类型),即不能通过创建的实例追溯到生成这个实例的函数,不好理解的话研究下构造函数模式;

二、构造函数模式

1.使用new关键字来调用

2.函数名首字母必须大写

function Person(name, age, job) {

  this.name = name;

  this.age = age;

  this.job = job;

  this.sayName = function () {

    alert(this.name);

  };

}

var person1 = new Person("Nike", 29, "teacher");

var person2 = new Person("Arvin", 20, "student");

/**

 * 要创建Person的新实例,必须使用new操作符,以这种方式调用构造函数实际会经历以下几个步骤:

 * 1.创建一个新对象

 * 2.将构造函数的作用域赋给新对象(因此this也就指向了这个新对象)

 * 3.执行构造函数中的代码(为这个新对象添加属性)

 * 4.返回新对象

 */

使用构造函数创建的实例,可以通过instanceof来判断函数的类型

console.log(person1 instanceof Object) // true

// 通过new Person 创建的对象既是Person的实例也是Object的实例

console.log(person1 instanceof Person) // true

看到这里不容易理解的话,研究下原型模式

三、原型模式

我们每创建一个函数都有一个prototype属性,这个属性是一个指针,指向一个对象,而这个对象的用途是可以包含由特定类型的所有实例共享的属性和方法

function Person() {}

Person.prototype.name = "Nike";

Person.prototype.age = 20;

Person.prototype.job = "teacher";

Person.prototype.sayName = function () {

  alert(this.name);

};

var person1 = new Person();

person1.sayName(); // "Nike"

 

解决了构造函数中每个方法都要在实例上创建一遍的问题;

缺点:在原型中定义属性,将与所有实例共享,因为它省略了初始化传参,所有实例都将在默认情况下取得相同的属性值;

此处扩展一下:

js创建对象的几种模式

每个构造函数都有一个prototype属性,它指向该构造函数的实例对象,该对象中保存着该构造函数的属性和方法,通过new关键字创建的实例都将共享这些属性和方法,因为原型链,查找对象的属性和方法的顺序,是先查找实例上是否有该方法,然后再查找该实例的构造函数中是否有这个方法,person1实例中并没有name属性,但是它的构造函数Person有这个属性,所以:

console.log(person1.name) // "Nike"