方式一:对象的动态特效 给原型对象添加成员
语法:构造函数.prototype.方法名=function (){ }
方式二:替换原型对象(不是覆盖,而是替换,把原先的同名的直接替换成现在的)
语法:构造函数.prototype.方法名={ }
tips:方式二不常用,因为这样会修改了原型本身
① 通过原型法分配的函数是所有对象共享的.
② 通过原型法分配的属性是独立.(如果你不修改属性,他们是共享)
③ 建议:如果我们希望所有的对象使用同一一个函数,最好使用原型法添加函数,这样比较节省内存.
构造函数方法很好用,但是存在一个浪费内存的问题。
请看,我们现在为Student对象添加一个不变的属性"sex"(性别),再添加一个方法eat(吃)。那么,原型对象Student就变成了下面这样:
function Student(name, age) {
this.name = name;
this.age = age;
this.sex = "人妖";
this.eat = function () {
alert("吃地沟油");
};
}
还是采用同样的方法,生成实例:
var p1 = new Student('张三', '24');
var p2 = new Student('李四', '18');
alert(p1.sex); //人妖
p1.eat(); //吃地沟油
表面上好像没什么问题,但是实际上这样做,有一个很大的弊端。那就是对于每一个实例对象,sex属性和eat()方法都是一模一样的内容,每一次生成一个实例,都必须为重复的内容,多占用一些内存。这样既不环保,也缺乏效率。
alert(p1.eat == p2.eat); //false
能不能让sex属性和eat()方法在内存中只生成一次,然后所有实例都指向那个内存地址呢?回答是可以的。
- Prototype模式
Javascript规定,每一个构造函数都有一个prototype属性,指向另一个对象。这个对象的所有属性和方法,都会被构造函数的实例继承。
这意味着,我们可以把那些不变的属性和方法,直接定义在prototype对象上。
function Student(name, age) {
this.name = name;
this.age = age;
}
Student.prototype.sex = "人妖";
Student.prototype.eat = function () {
alert("吃地沟油")
};
然后,生成实例。
var p1 = new Student("张三", "24");
var p2 = new Student("李四", "18");
alert(p1.sex); // 人妖
p1.eat(); // 吃地沟油
这时所有实例的type属性和eat()方法,其实都是一个内存地址,指向prototype对象,因此就提高了运行效率。
alert(p1.eat == p2.eat); //true
总结
1、把方法写在原型中比写在构造函数中消耗的内存更小,因为在内存中一个类的原型只有一个,写在原型中的行为可以被所有实例共享,实例化的时候并不会再实例中复制一份。而写在类中的方法,实例化的时候会在每一个实例对象中在复制一份,所以消耗的内存更高。因此没有特殊原因,我们一般把属性定义在类中,行为定义在原型中。
2、在构造函数中定义的属性和方法要比原型中定义的属性和方法优先级高,如果定义了同名称的属性和方法,构造函数中的将会覆盖原型中的。