说明:
在ECAMscript6出现了class(类),而在ECAMscript5和以前没有class,所以在ECAMscript5和以前的使用构造函数来代替class,但是构造函数有一个缺陷就是每实例化一个对象都会对对象里面的属性和方法重新开辟一个空间,在某些时候就造成了资源的浪费,然后他们为了在ECAMscript5和以前的版本解决这问题添加了prototype属性。
在JavaScript里面,每一个构造函数都有一个prototype属性,且prototype指向一个对象,所以可以理解为prototype就是一个对象,而这对象具有的属性和方法都会被他的构造函数所拥有(所以可以通过实例化对象来调用),这样我们就可以把哪些不变的方法和属性直接定义到prototype里面,让实例化对象共享这些方法和属性(prototype让那些不变的方法和属性指向同一地址)。
prototype的方法和属性是在构造函数外声明的,那实例化对象为什么有在函数外声明的方法和属性呢?这是因为每一个对象在实例化的时候,会自动添加__proto__属性,并且__proto__指向构造函数的原型对象prototype,所以prototype===proto。
但是如果构造函数里面的方法和属性与prototype重复了怎么办呢,他会这样办——先看这个实例化对象的__proto__有没有这个方法,如果有就执行这个方法,如果没有就到prototype里面去看看有没有这方法,如果有就执行这个方法没有就报错。。。
具体使用(js):
function Stu(uname,age) { //构造函数
this.uname=uname;
this.age=age;
this.sing=function () { //在构造函数里面添加一个方法
console.log('你好,我在唱歌');
}
}
Stu.prototype.dance=function () { //在函数外使用prototype添加一个方法
console.log('你好,我在跳舞');
};
Stu.prototype.sing=function () { //添加一个重复的方法
console.log('你好,我没有在唱歌');
};
var ming=new Stu('李明',20); //实例化对象
var hua=new Stu('李华',22);
console.log(ming.sing===hua.sing); //false,也恰好证明了不同的实例化对象的同一方法指向不同的地址
console.log(ming.dance===hua.dance); //ture,证明了使用prototype可以共享方法和属性,指向了同一地址
console.log(ming.__proto__===Stu.prototype); //ture
ming.sing(); //输出:你好,我在唱歌
上图: