0.基础
- javascript没有类的概念, javascript不需要实例化某个具体类的实例.javascript对象本身可以用来创建对象, 而对象可以继承自其他对象, 这个概念称为原型式继承
- 每个函数都包含prototype属性, 这个属性指向函数的原型对象, 这个属性不可枚举
- 默认情况下, 每个原型对象(prototype指向的那个对象)都会自动获得一个constructor属性, 这个属性反向指向构造函数
- 当调用一个构造函数创建一个新实例后, 这个实例内部包含一个指针指向构造函数的原型对象(即是构造函数的prototype属性指向那个对象)
- 每当代码读到某个属性的时候, 都会执行一次搜索, 目标是给定名称的属性. 首先会搜索自身, 如果在实例本身找到这个属性, 则返回属性值; 如果没有找到, 会继续查找这个实例的原型对象, 如果在原型对象中找到该属性, 则返回属性值; 如果没有找到, 这会沿着原型链一直搜索, 直到找到为止. 这是普遍的对象都会拥有Object, Array, String...的特性的原因
- 如果我们给实例添加原型中已经存在的属性(相同名称), 由于javascript通过原型链查找属性的特性, 新添加的属性会覆盖原型中的属性, 但是原型中的属性值还是存在的. 如果想要恢复访问原型中的属性的话, 把实例中的属性设置为null是不行的, 必须删除实例中的属性(deleta操作符)才能恢复访问原型中的属性值
1.一个例子
function Person(name) {
this.name = name;
}
Person.prototype.getName() = function() {
return this.name;
}
function User(name, password) {
this.name = name;
this.password = password;
}
//这里把User函数的原型设置为new Person()的结果
User.prototype = new Person();
//给原型对象添加一个新方法, 这个方法马上反映到User所有实例中
User.prototype.getPassword = function() {
return this.password;
}
这个例子最重要的User.prototype = new Person();这一行, new Person()使用Person构造函数构造一个新Person对象, 然后把User构造函数的原型置为这个操作的结果.
console.log(Person.prototype); //{ getName: [Function] }
console.log(User.prototype); //{ name: undefined, getPassword: [Function] }
由此可见, 最后一行代码新添加的getPassword是添加在new Person()生成的实例上的(即是User.prototype指向那个对象)
现在, 整个代码看起来是这样组织的