整理JavaScript创建对象的八种方法

javascript创建对象的方法如下所示:

1. 使用Object构造函数来创建一个对象

下面代码创建了一个person对象,并用两种方式打印出了Name的属性值。

var person = new Object(); person.name="kevin"; person.age=31; alert(person.name); alert(person["name"])

上述写法的另外一种表现形式是使用对象字面量创建一个对象,不要奇怪person[“5”],这里是合法的;另外使用这种加括号的方式字段之间是可以有空格的如person[“my age”].

var person = { name:"Kevin", age:31, 5:"Test" }; alert(person.name); alert(person["5"]);

虽然Object 构造函数或对象字面量都可以用来创建单个对象,但这些方式有个明显的缺点:使用同一个接口创建很多对象,会产生大量的重复代码。为解决这个问题,人们开始使用工厂模式的一种变体。

2、工厂模式

工厂模式是软件工程领域一种广为人知的设计模式,这种模式抽象了创建具体对象的过程,考虑到在ECMAScript 中无法创建类,开发人员就发明了一种函数,用函数来封装以特定接口创建对象的细节,如下面的例子所示。

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("Nicholas", 29, "Software Engineer"); var person2 = createPerson("Greg", 27, "Doctor");

工厂模式虽然解决了创建多个相似对象的问题,但却没有解决对象识别的问题(即怎样知道一个对象的类型)。随着JavaScript
的发展,又一个新模式出现了。

3. 构造函数模式

像Object 和Array 这样构造函数,在运行时会自动出现在执行环境中。此外,也可以创建自定义的构造函数,从而定义自定义对象类型的属性和方法。例如,可以使用构造函数模式将前面的例子重写如下。 

function Person(name, age, job){ this.name = name; this.age = age; this.job = job; this.sayName = function(){ alert(this.name); }; } var person1 = new Person("Nicholas", 29, "Software Engineer"); var person2 = new Person("Greg", 27, "Doctor");

在这个例子中,Person()函数取代了createPerson()函数。我们注意到,Person()中的代码除了与createPerson()中相同的部分外,还存在以下不同之处:

1、 没有显式地创建对象;

2、 直接将属性和方法赋给了this 对象;

3、 没有return 语句。

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

(1) 创建一个新对象;
(2) 将构造函数的作用域赋给新对象(因此this 就指向了这个新对象);
(3) 执行构造函数中的代码(为这个新对象添加属性);
(4) 返回新对象。

在前面例子的最后,person1 和person2 分别保存着Person 的一个不同的实例。这两个对象都有一个constructor(构造函数)属性,该属性指向Person,如下所示。

alert(person1.constructor == Person); //true
alert(person2.constructor == Person); //true

对象的constructor 属性最初是用来标识对象类型的。但是,提到检测对象类型,还是instanceof操作符要更可靠一些。我们在这个例子中创建的所有对象既是Object 的实例,同时也是Person的实例,这一点通过instanceof 操作符可以得到验证。

alert(person1 instanceof Object); //true
alert(person1 instanceof Person); //true
alert(person2 instanceof Object); //true
alert(person2 instanceof Person); //true

创建自定义的构造函数意味着将来可以将它的实例标识为一种特定的类型;而这正是构造函数模式胜过工厂模式的地方。在这个例子中,person1 和person2 之所以同时是Object 的实例,是因为所有对象均继承自Object。

构造函数的问题

构造函数模式虽然好用,但也并非没有缺点。使用构造函数的主要问题,就是每个方法都要在每个实例上重新创建一遍。

ECMAScript 中的函数是对象,因此每定义一个函数,也就是实例化了一个对象。从逻辑角度讲,此时的构造函数也可以这样定义。

function Person(name, age, job){
    this.name = name;
    this.age = age;
    this.job = job;
    this.sayName = new Function("alert(this.name)"); // 与声明函数在逻辑上是等价的
}

从这个角度上来看构造函数,更容易明白每个Person 实例都包含一个不同的Function 实例(以显示name 属性)的本质。说明白些,以这种方式创建函数,会导致不同的作用域链和标识符解析,但创建Function 新实例的机制仍然是相同的。因此,不同实例上的同名函数是不相等的,以下代码可以证明这一点。

alert(person1.sayName == person2.sayName); //false

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wgzsgs.html