JavaScript创建对象的几种方式

来源:互联网 发布:cadence软件仿真教程 编辑:程序博客网 时间:2024/06/06 04:16

ECMA-262把对象定义为:”无序属性的集合,其属性可以包含基本值、对象或者函数”。
我们可以把ECMAScript的对象想象成是拥有属性和方法的数据。

1.属性类型

[Configurable] //默认true,表示能否从对象中删除属性。[Enumerable]   //默认true,表示能否通过for-in循环返回属性[Writable]     //默认true,表示能否修改属性的值[Value]        //默认undefined

var person = {};
Object.defineProperty(person, “name”, {
configurable: false,
value: “Nicholas”
});

  person.name = "Nicholas";//静态属性name  person.sayName = function () {//动态属性sayName就是对静态属性那么的操作    alert(this.name);}

1.object的构造函数
创建自定义对象最简单的方式就是创建一个object的实例,然后为它添加属性和方法,早期JavaScript开发人员经常使用这个模式创建新对象。

var person = new Object();    person.name = "Nicholas";    person.age = 29;    person.job = "Software Engineer";    person.sayName = function () {    alert(this.name);}

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

var person = {    name: "Nicholas",    age:29,    job:"Software Engineer",    sayName: function () {    alert(this.name);    }};

3.工厂模式
定义:开发人员用一种函数封装以特定接口创建对象的细节
存在的问题:工厂模式虽然解决了创建多个相似对象的问题,但却没有解决对象识别的问题(即怎样知道一个对象的类型)。

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");

4.构造函数模式
解决问题:解决对象识别的问题(即怎样知道一个对象的类型)
存在的问题:
1.在全局作用域中定义的函数实际上只能被某个对象(person1,person2)调用,这让全局作用域有点名不副实。
2.如果对象需要定义很多方法,就要定义很多个全局函数,于是我们这个自定义的引用类型就丝毫没有封装性可言。
规则:构造函数始终应以一个大写字母开头,非构造函数则应以小写字母开头
原生构造函数:Object和Array
自定义的构造函数,如下所示
1.person1和person2都有一个sayName()的方法,但那两个方法不是同一个Function的实例。

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");

2.通过把函数定义到构造函数外面解决这个问题

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

5.原型模式
解决的问题:
1.不必再构造函数中定义对象实例的信息,而是可以将这些信息直接添加到原型对象(prototype)中。
2.可以让所有实例对象 (var person1 = new Person(); ) 共享它所包含的属性和方法。
存在的问题:
向friends数组添加一个字符串,由于数组存在于prototype属性中,添加字符串也会通过person2.friends反映出来。

function Person() {}Person.prototype.name = "Nicholas";Person.prototype.age = 29;Person.prototype.job = "Software Engineer";Person.prototype.friends= ["Shelby","Court"];Person.prototype.sayName = function () {alert(this.name);}var person1 = new Person();var person2 = new Person();person1.friends.push("Van");alert(person1.friends);alert(person2.friends);alert(person1.friends == person2.friends);

6.组合使用构造函数和原型模式(推荐)

function Person(name, age, job) {this.name = name;this.age = age;this.job = job;this.friends = ["Shelby", "Court"];}Person.prototype = {constructor:Person,sayName :function () {alert(this.name);}}var person1 = new Person("Nicholas", 29, "Software Engineer");var person2 = new Person("Greg", 27, "Doctor");person1.friends.push("Van");alert(person1.friends);      //"Shelby,Count,van"alert(person2.friends);     //"Shelby,Count"alert(person1.friends === person2.friends);    //falsealert(person1.sayName === person2.sayName);   //true
0 0
原创粉丝点击