JS面向对象之对象的创建

考虑到后续的应用需要,特将JS面向对象的东西再复习梳理重新认识一遍。

JS 创建对象的方式有不少,目前主要受推重的方式是组合模式(构造函数模式结合原型模式)。下面分别介绍、层层推进笔记。

1早期创建对象new模式

实例化一个对象,然后用点号.给实例赋予属性、方法。

1
2
3
4
5
6
7
8
var person=new Object();
// var person={}; //或创建一个空对象
person.name="guo";
person.age="20";
person.jop="web qianduan";
person.sayName=function(){
alert(this.name);
};

2对象字面量创建对象模式(推荐)

对第1种进行改造,变成对象字面量,更简介方便:

1
2
3
4
5
6
7
8
9
var person={
name:"guo",
age:20,
jop:"web qianduan",
sayName:function(){
alert(this.name);
}
};
person.sayName();

3工厂模式

可以无数次调用这个函数,而每一次都会返回一个包含三个属性一个方法的对象;工厂模式解决了创建多个相似对象的问题;但没有解决对象识别问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
function createPerson(name,age,jop){
var o=new Object();
o.name=name;
o.age=age;
o.jop=jop;
o.sayName=function(){
alert(this.name);
};
return o;
}
var person1=createPerson('guo1',201,'web qianduan1');
var person2=createPerson('guo2',202,'web qianduan2');
person2.sayName();

4构造函数模式

先上代码:

1
2
3
4
5
6
7
8
9
10
11
12
function Person(name,age,jop){
this.name=name;
this.age=age;
this.jop=jop;
this.sayName=function(){
alert(this.name);
};
}
var person1=new Person('guo1',201,'web qianduan1');
var person2=new Person('guo2',202,'web qianduan2');
person2.sayName();

构造函数模式与 3工厂模式的区别:

  1. 没有显式地创建对象;
  2. 直接将属性和方法赋给了this对象;
  3. 没有return语句。

构造函数的函数名的首字母一般是大写字母:Person;

要创建Person的新实例,得使用new操作符;此方式调用构造函数会经历一下4个步骤:

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

构造函数存在的问题:每一次生成一个新实例,三个属性一个方法全部都被重新创建一次;每个实例,三个属性不同、理应要重新创建;但是相同的一个方法 sayName ,被重复创建,占用了内存。

5原型模式

读取person1.name时,先在实例上搜索一个名为name的属性;存在就返回、不再搜索原型了。对象实例添加属性会屏蔽原型对象相同的属性,但不会修改原型的属性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
function Person(){}
Person.prototype.name='guo';
Person.prototype.age=20;
Person.prototype.jop='web qianduan';
Person.prototype.sayName=function(){
alert(this.name);
};
var person1=new Person();
var person2=new Person();
person1.name='guo1';
alert(person1.name); //guo1,来自实例
alert(person2.name); //guo,来自原型
//原型模式字面量,只敲一遍Person.prototype
function Person(){}
Person.prototype={
name:'guo',
age:20,
jop:'web qianduan',
sayName:function(){
alert(this.name);
}
};

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,jop){
this.name=name;
this.age=age;
this.jop=jop;
this.friends=['li','zhao'];
}
Person.prototype={
constructor:Person,
sayName:function(){
alert(this.name);
}
}
var person1=new Person('guo1',201,'web qianduan1');
var person2=new Person('guo2',202,'web qianduan2');
person1.friends.push('wang');
alert(person1.friends); //li,zhao,wang
alert(person2.friends); //li,zhao
alert(person1.friends==person2.friends); //false
alert(person1.sayName==person2.sayName); //true

原型模式的一些验证方法

isPrototypeOf():判断某个proptotype对象某个实例之间的关系,如:

1
2
alert(Person.prototype.isPrototypeOf(person1)); //true
alert(Person.prototype.isPrototypeOf(person2)); //true

hasOwnProperty():每个实例对象都有一个hasOwnProperty()方法,用来判断某一个属性到底是本地属性,还是继承自prototype对象的属性。如:
alert(person1.hasOwnProperty("name")); // true

in运算符:in运算符可以用来判断,某个实例是否含有某个属性,不管是不是本地属性。如:
alert("name" in person1); // true
in运算符还可以遍历某个对象的所有属性:

1
2
3
for(var prop in person1){
alert("person1["+prop+"]="+person1[prop]);
}

除此之外,JS创建对象还有其它一些方式:动态原型模式、寄生构造函数模式、稳妥构造函数模式。这里就暂且不管了,组合模式是比较常用的嘛。

学习参考:
JavaScript高级程序设计(第3版)
Javascript 面向对象编程(一)