上一章构造函数确实简化了多个对象创建的麻烦问题,但是:构造函数每创建一个实例,构造函数就会执行一次,将属性和方法添加到该对象,每个对象实例化后地址互不相同,即使它们的方法所实现的逻辑和功能一样,但确不是同一个方法,这样每次调用,系统都会开辟空间来创建一个(实现同一个逻辑和功能的)方法,从而影响性能,这样的代码显得多余。那么可不可以放全局域中吗?可以,但是会占用全局域命名空间(别的函数不能再同名),而且定义在全局作用域中会很不安全(其他程序员万一同名了,代码就乱了)。因此,我们有必要优化代码。可不可以让相同的属性或方法放在公共区域,被多个实例化的不同对象调用呢?
<script>
function Person(name,age,grade,id)
{
this.name = name;
this.age = age;
this.grade = grade;
this.show_id = function()
{
console.log(this.id);
}
}
var per11 = new Person("张三",16,6,"0001");
var per22 = new Person("李四",21,8,"0002");
// 结果:false,证明对象实例化后方法不一样。
console.log(per11.show_id == per22.show_id);
</script>
原型、原型对象
原型(prototype):是函数的一个特殊属性,即指针指向原型对象。
原型对象(prototype object):是一个属于其所在函数的空对象,可以添加属性和方法。其自身constructor属性指向其函数。
解释:
原型对象相当于一个公共的区域,同一个类(构造函数)的实例化的对象都可以访问到这个原型对象。为了优化性能,我们可以将该类中共有的属性和方法统一放入到原型对象中。
对应关系:
1、每一个对象都有一个属性叫__proto__,它指向了一个对象,这个对象我们叫原型对象。
2、每一个构造器(类,函数),也是对象,也有一个属性叫prototype,它也指向一个对象,和__proto__指向同一个对象,也是原型对象。
3、每一个原型对象上,都是有一个属性叫constructor,它指向此原型对象所对应的构造器。
访问机制(原型链):
当我们访问对象的一个属性或方法时,它会先在对象自身中寻找,如果有则直接使用,如果没有则就沿着__proto__会去原型对象中寻找,如果找到则直接使用,如果没用则去原型的原型中寻找,直到找到Object对象的原型,Object对象的原型没有原型,如果在Object中还没有找到则返回undefined。
原型对象的用法:
1、利用对象的动态特性完成添加
语法:构造函数名.prototype.xxxx=yyyy
2、直接替换
语法:构造函数名.prototype={};
示例:
<script>
function Person(name,age,grade)
{
this.name = name;
this.age = age;
this.grade = grade;
}
// 把方法放入原型对象
Person.prototype.show_id = function(id){
console.log(id);
}
// 实例化一个对象per11
var per11 = new Person("张三",16,6);
per11.show_id("0001");
console.log(per11);
// 修改原型对象内容
Person.prototype =
{
show_id:function(id)
{
console.log("您的id号为",id);
}
}
// 修改原型对象后,再实例化对象per22
var per22 = new Person("李四",21,8);
per11.show_id("0001");
per22.show_id("0002");
</script>
解析图所示:
运行结果: