1:原型和原型链
原型
在 JavaScript 中,对象有一个特殊的隐藏属性
[[Prototype]]
(如规范中所命名的),它要么为null
,要么就是对另一个对象的引用。该对象被称为“原型”
每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,实例都包含一个指向原型对象的内部指针。(实例都有一个属性叫做_proto_指向原型对象Object.prototype)谷歌浏览器的实现就是将
[[Prototype]]
命名为__proto__
function Person() {}
Person.prototype.name = "zhangsan";
Person.prototype.age = 29;
Person.prototype.gender = "male";
Person.prototype.sayName = function () {
console.log(this.name);
};
// 使用构造函数创建实例对象
var person1 = new Person();
// 构造函数
console.log(Person);//ƒ Person() {}
//原型对象 Person.prototype
console.log(Person.prototype); //{name: 'zhangsan', age: 29, gender: 'male', sayName: ƒ, constructor: ƒ}
// 原型对象中的constructor属性 原型对象中的constructor属性指向构造函数
console.log(Person.prototype.constructor); //[Function: Object]
// 实例__proto__ 指向 原型对象
console.log(person1.__proto__ === Person.prototype); //true
原型链
每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针。那么假如我们让原型对象等于另一个类型的实例,结果会怎样?显然,此时的原型对象将包含一个指向另一个原型的指针,相应地,另一个原型中也包含着一个指向另一个构造函数的指针。假如另一个原型又是另一个类型的实例,那么上述关系依然成立。如此层层递进,就构成了实例与原型的链条。这就是所谓的原型链的基本概念
当我们从
object
中读取一个缺失的属性时,JavaScript 会自动从原型中获取该属性。在编程中,这被称为“原型继承”。
function Animal() {
this.name = 'animal';
}
Animal.prototype.getAnimalName = function () {
console.log(this.name + 'getAnimalName');
}
// 创建Dog
function Dog() {
this.name = 'dog';
}
// Dog继承自Animal 将Animal的实例赋值给Dog的原型对象,相当于将Animal的实例中的__proto__赋值给了Dog的原型对象
// 如此 Dog原型对象 就能通过 Animal 对象的实例中的[[prototype]](__proto__) 来访问到 Animal原型对象 中的属性和方法了。
Dog.prototype = new Animal();
console.log(Dog.prototype);
// console.log(Animal.prototype);
Dog.prototype.getDogName = function () {
console.log(this.name + 'getDogName');
}
var d1 = new Dog();
console.log(d1);
d1.getAnimalName() //doggetAnimalName
d1.getDogName() //doggetDogName
2:prototype与__proto__的关系与区别
1:_proto_和constructor属性是对象独有的
2:prototype属性是函数独有的,但是函数在js中也是一个对象,所以函数也有_proto_和constructor这两种属性。
3:继承的实现方式及比较
当我们从
object
中读取一个缺失的属性时,JavaScript 会自动从原型中获取该属性。在编程中,这被称为“原型继承”。