1.javascript原型
1.1.函数的原型对象
我们创建一个函数,浏览器就会为我们在内存中创建一个原型对象,每个函数默认会
有一个prototype属性,这个prototype就指向这个函数的原型对象,这个原型对象就
函数的原型,同时这个原型对象里面会有一个constructor属性,这个constructor属性
指向的就是这个函数(可以理解为原型对象是类,函数是构造方法)。
1.2.原型模型创建对象的缺陷
原型中的所有属性都是共享的,同一构造创建的对象,去访问原型中的属性,每个
对象访问的都是同一个属性,但每个对象的属性都是不一样的,但是对于方法来说
但是,这个共享特性对 方法(属性值是函数的属性)又是非常合适的。
1.3.构造函数模型创建对象的缺陷
在构造函数中添加的属性和方法,每个对象都有自己独有的一份,大家不会共享。
这个特性对属性比较合适,但是对方法又不太合适。因为对所有对象来说,他
们的方法应该是一份就够了,没有必要每人一份,造成内存的浪费和性能的低下。
1.4.使用组合模式解决上述两种缺陷
原型模式适合封装方法,构造函数模式适合封装属性,综合两种模式的优点就有了
组合模式。
<script type="text/javascript">
//在构造方法内部封装属性
function Person(name, age) {
this.name = name;
this.age = age;
}
//在原型对象内封装方法
Person.prototype.eat = function (food) {
alert(this.name + "爱吃" + food);
}
Person.prototype.play = function (playName) {
alert(this.name + "爱玩" + playName);
}
var p1 = new Person("李四", 20);
var p2 = new Person("张三", 30);
p1.eat("苹果");
p2.eat("香蕉");
p1.play("志玲");
p2.play("凤姐");
</script>
1.5动态原型模式创建对象
前面讲到的组合模式,也并非完美无缺,有一点也是感觉不是很完美。把构造方法
和原型分开写,总让人感觉不舒服,应该想办法把构造方法和原型封装在一起,所
以就有了动态原型模式。动态原型模式把所有的属性和方法都封装在构造方法中,
而仅仅在需要的时候才去在构造方法中初始化原型,又保持了同时使用构造函数
和原型的优点。
<script type="text/javascript">
//构造方法内部封装属性
function Person(name, age) {
//每个对象都添加自己的属性
this.name = name;
this.age = age;
/*
判断this.eat这个属性是不是function,如果不是function则证明是第一次创建对象,
则把这个funcion添加到原型中。
如果是function,则代表原型中已经有了这个方法,则不需要再添加。
perfect!完美解决了性能和代码的封装问题。
*/
if(typeof this.eat !== "function"){
Person.prototype.eat = function () {
alert(this.name + " 在吃");
}
}
}
var p1 = new Person("志玲", 40);
p1.eat();
</script>