js创建对象的三种形式(详细)
前言: 为了省去Object 构造函数和对象字面量创建对象的大量重复代码,人们开始使用工厂模式的一种变体
1. 工厂模式
-
工厂模式是一种广为人知的设计模式, 这种模式抽象了创建具体对象的过程。考虑到在ECMAScript中无法创建类,开发人员就发明了以一种函数,用函数来封装以特定的接口创建对象的细节
-
// 工厂模式 function createPerosn(name, age, job){ var o = new Object(); o.name = name; o.age = age; o.job = job; o.sayName = function(){ // this 指向的是o alert(this.name); } return o; } // 创建实例 var person1 = createPerson('Tom', 29, 'software');
-
工厂模式虽然解决了创建多个和相似对象的问题,但却没有解决对象识别的问题,(即这样创建的实例无法知道该实例由什么那个函数创建, 即无法知道一个对象的类型)。随着JavaScript的发展,又一个新模式出现了。
2. 构造函数模式
-
ECMAScript中构造函数可用来创建特定类型的对象。因此,我们可以创建自定义的构造函数,从而定义自定义对象类型的属性和方法。例如,可以使用构造函数模式将前面的例子重写下。
-
// 构造函数模式 function Person(name, age, job) { this.name = name; this.age = age; this.job = job; this.sayName = function () { alert(this.name); } }
-
我们可以发现 Person() 与 createPerson() 不同之处为
- 没有显式的创建对象 ,
- 直接将属性和方法直接赋给了this对象
- 没有 return 语句
-
构造函数始终都应该以一个大写字母开头
-
要创建Person新实例,必须使用new操作符,这种方式的调用构造函数会经历一下4个步骤:
- 创建一个新对象 var person = {} , person 的 _ proto _ 指向构造函数的原型对象 ,原型链的开始
- 将构造函数的作用域赋给这个新对象 ( 这个时候 this 指向这个新对象)
- 执行构造函数中的代码(为这个对象添加属性)
- 返回新对象
-
构造函数的问题
-
相同实例的方法多次创建, 即创建两个有相同任务的Function sayName() 函数实例没a有必要 。所以,Person() 函数可以像下面这样写
function Person(name, age, job) { this.name = name; this.age = age; this.job = job; this.sayName = sayName; } function sayName() { alert(this.name); }
-
这样是解决了每次创建实例时创建相同任务的 sayName 函数的浪费,但是将 sayName() 函数放在全局是一种非常不好的方式, 我们失去了函数的封装性,所以就出现了原型模式
-
3. 原型模式
-
我们创建的每一个函数都有一个 prototype 属性,这个属性是一个指针。指向一个对象,而这个对象用途是包含可以由特定类型的所有实例共享的属性和方法。使用原型对象的好处是可以让所有对象实例共享它所包含的属性和方法。换句话说,不必在构造函数中定义对象实例的信息,而是可以将这些信息直接添加到原型对象中,如下所示
function Person(){ } Person.prototype.name = 'Tom'; Person.prototype.age = 16; Person.prototype.job = 'software Engineer'; Person.prototype.sayName = function(){ alert('this.name'); }