原型与原型链
构造函数的显示原型对象 === 当前构造函数的实例对象的隐式原型对象
- 原型就是一个对象。其
目的就是为了给其他对象提供共享数据的对象
。
函数对象, 本身是对象,也可以通过对象名()的方式执行函数的功能。
普通对象 , 就是个对象,不能直接对象名()来调用函数。
- 构造函数。c1,c2是Car的实例对象,它们有一个
构造器属性(constructor)
,指向当前的构造函数。
function Car(name) {
this.name = name;
}
var c1 = new Car('c1');
var c2 = new Car('c2');
console.log(c1.constructor === Car); //true
- 原型对象
js,每定义一个对象(函数也是对象),都会有默认的属性。所以每个函数对象中都有一个prototype属性,该属性指向该函数的原型对象
这里注意,每个对象都有__proto__属性,但只有函数对象才有prototype属性
- 在默认情况下,
所有的原型对象都会自动获得一个 constructor(构造函数)属性
, 这个属性(是一个指针)指向 prototype 属性所在的函数(Car). - 上述的构造函数中,实例对象
同样也有构造器属性
,指向当前构造函数。 - 因此,原型对象(Car.prototype)是 函数对象(Car)的一个实例(目的就是指出原型就是个对象。)
function Person(name) {
this.name = name;
}
var p1 = new Person();
console.log(Person.prototype.__proto__ === Object.prototype);
console.log(Object.prototype.__proto__ === null);
console.log(Object.__proto__ === Function.prototype);
console.log(Function.__proto__ === Function.prototype);
console.log(Function.prototype.__proto__ === Object.prototype);
//true true true true true
所有的函数,包括构造函数和内置的Object()函数,都是Function()的实例对象(结合下图的Function() 与 Object()来理解。
继承
- 原型链继承
- 每个构造函数都有一个原型对象,原型对象中都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针。当原型对象等于另外一个类型的实例即继承。
function Animal(){ this.name = "animal" } Animal.prototype = { sayName : function(){ alert(this.name); } } //定义子类类型 function Dog(){ this.color = "灰色" } //通过将子对象的原型对象指向父对象的一个实例来完成继承 Dog.prototype = new Animal(); //子对象的方法其实是定义在了符类对象的实例上。 Dog.prototype.sayColor = function(){ alert(this.color); } var dog = new Dog(); console.log(dog); dog.sayColor(); dog.sayName();
- 问题:
- 通过原型来实现继承时,原型实际上会变成另一个类型的实例,原来的实例属性也就变成了现在的原型属性。
- 在创建子类型的实例时,不能向超类型的构造函数传递参数。因此实践中很少会单独使用原型链。
- 借用构造函数
- 也称 “伪造对象” 或 “经典继承”,在子类型构造函数的内部调用超类型构造函数。
function Animal(name){ this.name = name; this.colors = ["red","gray"]; } function Dog(name){ //继承了Animal Animal.call(this,name); this.color = "gray"; } Animal.prototype.sayName = function(){ alert(this.name); }
- 组合函数
- 也称"伪经典继承",将原型链和借用构造函数的技术组合在一起。原理是:使用原型链实现对原型属性和方法的继承,而通过借用构造函数实现对实例属性的继承。
function Animal(name){ this.name = name; this.colors = ["red","gray"]; } function Dog(name){ //继承了Animal(属性) Animal.call(this,name); this.color = "gray"; } Animal.prototype.sayName = function(){ alert(this.name); } //继承方法 Dog.prototype = new Animal(); Dog.prototype.constructor = Dog;