关于JavaScript对象

JavaScript对象的概念及创建方式

ECMAScript中没有类的概念。ECMA-262把对象定义为:“无序属性的集合,其属性可以包含基本值、对象或函数。”

每个对象都是基于一个引用类型创建的。

创建对象的方法:


1、创建Object实例

1
2
3
4
5
6
7
8
var person = new Object();
person.name = "John";
person.age = 29;
person.job = "software engineer";
person.sayName = function(){
alert(this.name);
}

2、对象字面量

1
2
3
4
5
6
7
8
var person = {
name : "John",
age : 29,
job : "software engineer",
sayName : function(){
alert(this.name);
}
}

前两种方式的缺点:使用同一个接口创建很多对象,会产生大量的重复代码。

3、工厂模式
用函数封装以特定接口创建对象的细节:

1
2
3
4
5
6
7
8
9
10
11
12
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 person = createPerson("John",29,"software engineer");

4、构造函数模式
可以创建自定义的构造函数,从而定义自定义对象类型的属性和方法:

1
2
3
4
5
6
7
8
9
10
function Person(name,age,job){
this.name = name;
this.age = age;
this.job = job;
this.sayName = function() {
alert(this.name);
}
}
var person = newPerson("John",29,"software engineer");

构造函数始终都应该以一个大写字母开头

以new操作符调用构造函数会经历以下四个步骤:

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

不使用new操作符调用构造函数:属性和方法都被添加给window对象。

构造函数的缺点:每个方法都要在每个实例上重新创建一遍。创建多个完成相同任务的function实例其实没有必要。

5、原型模式
我们创建的每个函数都有一个prototype属性,这个属性是一个指针,指向一个对象,使用原型对象的好处是可以让所有对象实例共享它所包含的属性和方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function Person() {
}
Person.prototype.name = "John";
Person.prototype.age = 29;
Person.prototype.job = "software engineer";
Person.prototype.sayName = function() {
alert(this.name);
}
var person1 = new Person();
person1.sayName(); //John
var person2 = new Person();
person2.sayName(); //John
alert(person1.sayName == person2.sayName);//true

6、组合使用构造函数模式和原型模式
构造函数模式用于定义实例属性,而原型模式用于定义方法和共享的属性。这样,每个实例都会有自己一份实例属性的副本,但同时又共享着对方法的引用,最大限度地节省了内存。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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,court,van"
alert(person2.friends); //"shelby,court"
alert(person1.friends === person2.friends); //false
alert(person1.sayName === person2.sayName); //true

7、动态原型模式

1
2
3
4
5
6
7
8
9
10
11
12
function Person(name,age,job){
this.name = name;
this.age = age;
this.job = job;
if(typeof this.sayName != "function"){
Person.prototype.sayName = function(){
alert(this.name);
}
}
}
var friend = new Person("Nicholas",29,"software engineer");
friend.sayName();

这里只有在sayName()方法不存在的情况下,才会将它添加到原型中。

8、寄生构造函数模式
这种模式的基本思想是创建一个函数,该函数的作用仅仅是封装创建对象的代码,然后再返回新创建的对象;但从表面上看,这个函数又很像是典型的构造函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
function Person(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 friend = new Person("Nicholas",29,"software engineer");
friend.sayName();