function Person(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
this.friends = ['Shelby', 'Court'];
if (typeof this.sayName != 'function') {
Person.prototype = {
constructor: Person,
sayName: function() {
alert(this.name);
}
};
}
}
var person1 = new Person('Nicholas', 29, 'Software Engineer');
var person2 = new Person('Greg', 29, 'Doctor');
alert(person1.sayName === person2.sayName);但书中这种写法却返回true:function Person(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
this.friends = ['Shelby', 'Court'];
if (typeof this.sayName != 'function') {
Person.prototype.sayName = function() {
alert(this.name);
};
}
}
var person1 = new Person('Nicholas', 29, 'Software Engineer');
var person2 = new Person('Greg', 29, 'Doctor');
alert(person1.sayName === person2.sayName);
为什么会这样??
alert(person1.sayName);
alert(person2.sayName);
看看就知道了
constructor: Person,
sayName: function() {
alert(this.name);
}
};你new的时候 改变或者说 新建了 Person.prototype
那么 new的时候的这个object.prototype 指向你当前新建的Person.prototype
Person.prototype.sayName = function() {
alert(this.name);
};
书上的写法 Person.prototype 一直没变过 你永远指向这个Person.prototype
当你访问 sayName的时候 才开始从 prototype上开始查找sayName
那么 是一个地方
第一次new时,只是完成了新原型对象的定义,但是新的原型对象的属性方法并没有赋给person1,person1的原型对象仍然是原生的Person.prototype。因为原生的原型对象中并没有sayName这个方法,所以person1.sayName的值是“undefined”。
等到第二次new的时候,此时Person.prototype已被重写,所以person2会拥有重写后的原型对象中所有属性方法的,person2.sayName的值是“function(){alert(this.name)}”。(2)第二种就不用说了,~~直接在原生的原型对象上追加,person1和person2有着共同的原型对象,自然共享原型里的属性和方法。
但为什么第二次new时才生效?
这个估计要从new到底干了什么说起吧。new操作先创建空对象,然后链接对象的原型到构造器的原型上,然后再运行构造器。chrome下有个东东叫__proto__,这个家伙就是prototype的具体实现。var person1 = new Person();
//翻译一下new
var person1 = new Object();
person1.__proto__ = Person.prototype;
Person.call(person1);这俩是等价的。
接着看这个:var o = {};
var a = o;
o = {c:1};
b = o;
alert(a.c === b.c); //自然是false对照下来是这样:person1.__proto__ = Person.prototype;
Person.prototype = {sayName:function(){}};
person2.__proto__ = Person.prototype;
alert(person1.__proto__.sayName === person2.__proto__.sayName); //自然也是false但如果是这样:person1.__proto__ = Person.prototype;
Person.prototype.sayName = function(){};
person2.__proto__ = Person.prototype;
alert(person1.__proto__.sayName === person2.__proto__.sayName); //那就是true了我觉得引入__proto__更能帮助理解prototype原型链。
但为什么第二次new时才生效?
Person.prototype是在声明函数Person后就默认存在的,只不过是个没有添加属性和方法的空对象而已。为什么第二次才有效?因为第一次new之前,重写的原型对象还不存在,Person.prototype是原生的空原型对象。在第二次new之前,重写的原型对象Person.prototype(因为第一次new)已经存在,而且包含一个属性一个方法。
person1和person2各自的原型对象是不一样的,一个是空对象,一个是包含一个属性和一个方法的对象。