js的面向对象方式的函数有很多种方式,其中有两个比较重要的是两种方式一是构造函数模式,一是原型模式。
1、构造函数模式如:
function Persion(name,age) {
this.name = name;
this.age= age;
this.sayName = function() {
alert(this.name);
}
}
var person1 = new Person("Alex",29);
person1.sayName(); //"Alex"
var person2 = new Person("XiaoMing", 28);
person2.sayName(); //"XiaoMing"
要创建一个Person的实例,大致分为几步:
1) 使用new创建一个新对象
2)将构造函数的作用域赋给新对象(this指向当前对象)
3)执行构造函数中的代码
4)返回新对象
优点:结构简单
缺点:每个方法都要在每个实例上创建一遍
2、原型模式如:
每个函数都有一个prototype属性,即原型属性,它是一个指针,指向的是一个可以供函数的实例共享属性和方法的的对象。
function Persion(name,age) {
}
Person.prototype.name = "Alex";
Person.prototype.age= 29;
Person.prototype.sayName = function() {
alert(this.name);
}
var person1 = new Person();
person1.sayName(); //"Alex"
var person2 = new Person();
person2.sayName(); //"Alex"
创建一个函数就会有一个prototype的属性,指向一个原型对象。而原型对象会有一个constructor的属性,包含一个指针,又指向了prototype所在的函数。如:
因此,基于Person的两个实例对象都共享了Person的原型对象的属性和方法,因为他们指向了同一个对象。
实例在调用属性的时候首先会在自己的实例中去搜寻,如果没有找到则继续去原型对象中搜寻。所以我们给一个实例增加一个属性或者方法时,这个属性或方法会屏蔽原型对象中同名的属性或者方法。
原型的另一种简单写法:
function Person() {
}
Person.prototype = {
<strong>constructor:Person,</strong>
name:"Alex",
age:29,
sayName: function() {
alert(this.name);
}
}
此方法相当于重写了原型对象,特别需要注意增加constructor属性。
优点:可以让所有实例共享属性和方法
缺点:优点也是缺点,当实例操作某一个属性值时,别的实例因为访问的是同一个原型对象,所以取到的是变化后的值。
3、组合使用构造模式和原型模式
构造函数模式用于实例的属性,原型模式用于方法和共享的属性。这样,每个实例有一份实例属性的副本,同时共享方法的引用。
function Person(name,age) {
this.name = name;
this.age = age;
}
Person.prototype = {
constructor:Person,
sayName: function() {
alert(this.name);
}
}
var person1 = new Person("Alex",29);
var person2 = new Person("Xiaoming",28);
person1.sayName();//"Alex";
person2.sayName();//"Xiaoming"