function Person(name,age){
this.name = name;
this.age = age;
this.introduce = function(){
alert('我是'+this.name)
};
}
var p1 = new Person('小敏',12);
var p2 = new Person('小敏',12);
var p3 = new Person('小敏',12);
//.....................
如上不断地实例化Person对象,每次实例化都要为intrduce方法开辟新的内存空间,这样做浪费了内存空间
下面想了一个办法,在外部为方法写一个函数,让对象中的方法指向这个函数,当对象调用方法时,通过属性指向方法函数所在的地址,
那么就可以实现多个对象公用一个方法函数
function introduce(){
alert('我是'+this.name);
}
// var introduce = '你好'; //缺点当其他人定义变量与函数名相同时,会报错
function Person(name,age){
this.name = name;
this.age = age;
this.introduce = introduce;
}
//实例化对象
var p1 = new Person('小敏',12);
var p2 = new Person('小明',12);
p1.introduce(); //第5行有效 则 这里会报错
// console.log(p1.introduce == p2.introduce); //true
上面的代码依然存在缺陷,封装对象后,假如其他人看不到源码的情况下,且定义了一个与方法函数名相同的变量,那么这个程序将会报错,程序不能正常运行.
原型存在于每个函数对象中,是函数对象的属性 函数名.prototype.方法名 = function(){函数体} (当然我们也可以通过这种方式为构造函数添加属性)
function Person(name,age){
this.name = name;
this.age = age;
}
Person.prototype.introduce = function(){//prototype 原型,模式
alert('我是'+this.name);
};
//实例化对象
var p1 = new Person('小敏',12);
var p2 = new Person('小明',12);
p1.introduce();
console.log(p1.introduce == p2.introduce); //true
构造函数中存在一个属性叫 prototype 也就是原型,原型本身又是一个对象,它内部存储着 constructor 构造器,还用用户定义的需要共享的属性以及方法
prototype 原型对象中的constructor属性 指向的是prototype自己所在的构造函数
在实例化对象中存在着一个叫 __proto__的属性,同时它本身是一个对象,确切地说 它指向构造函数中的 prototype对象所在的内存空间,所以 __proto__ ==Prototype ,
但是__proto__是一个非标准化的对象, 它内部的方法 可以直接 被它的父级对象直接调用, 如上段代码中 introduce方法在 __proto__对象中, __proto__是p1的属性, 正常调用方式是 p1.__proto__.introduce(), 由于__proto__的非标准化, p1.introduce() 调用方法也是行得通的.