[JS]彻底理解原型链
Posted ouyangshima
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[JS]彻底理解原型链相关的知识,希望对你有一定的参考价值。
从一张图看懂原型对象、构造函数、实例对象之间的关系
function Dog();
Dog.prototype.name = "小黄";
Dog.prototype.age = 13;
Dog.prototype.getAge = function()
return this.age;
var dog1 = new Dog();
var dog2 = new Dog();
dog2.name = "小黑";
console.log(dog1.name); // 小黄 来自原型
console.log(dog2.name); // 小黑 来自实例
//图中的一些关系
dog1.__proto__ === Dog.prototype
Dog.prototype.__proto__ === Object.prototype //继承Object 下面原型链说
dog1.__proto__.__proto__ === Object.prototype
Dog.prototype.constructor === Dog
Dog.prototype.isPrototypeOf(dog1)
//获取对象的原型
dog1.__proto__ //不推荐
Object.getPrototypeOf(dog1) === Dog.prototype //推荐
1、prototype
在JavaScript中,每个函数都有一个prototype属性,这个属性指向函数的原型对象。
function Person(age)
this.age = age
Person.prototype.name = 'kavin'
var person1 = new Person()
var person2 = new Person()
console.log(person1.name) //kavin
console.log(person2.name) //kavin
上述例子中,函数的prototype指向了一个对象,而这个对象正是调用构造函数时创建的实例的原型,也就是person1和person2的原型。
原型的概念:每一个javascript对象(除null外)创建的时候,就会与之关联另一个对象,这个对象就是我们所说的原型,每一个对象都会从原型中“继承”属性。
2、__proto__
这是每个对象(除null外)都会有的属性,叫做__proto__,这个属性会指向该对象的原型。
function Person()
var person = new Person();
console.log(person.__proto__ === Person.prototype); // true
3、constructor
每个原型都有一个constructor属性,指向该关联的构造函数。
function Person()
var person = new Person();
console.log(Person.prototype.constructor === Person) // true
console.log(person.__proto__ === Person.prototype) // true
4、实例与原型
当读取实例的属性时,如果找不到,就会查找与对象关联的原型中的属性,如果还查不到,就去找原型的原型,一直找到最顶层为止。
function Person()
Person.prototype.name = 'Kevin';
var person = new Person();
person.name = 'Daisy';
console.log(person.name) // Daisy
delete person.name;
console.log(person.name) // Kevin
在这个例子中,我们给实例对象 person 添加了 name 属性,当我们打印 person.name 的时候,结果自然为 Daisy。
但是当我们删除了 person 的 name 属性时,读取 person.name,从 person 对象中找不到 name 属性就会从 person 的原型也就是 person.__proto__ ,也就是 Person.prototype中查找,幸运的是我们找到了 name 属性,结果为 Kevin。但是万一还没有找到呢?
原型链
原型链是实现继承的主要方法。
先说一下继承,许多OO语言都支持两张继承方式:接口继承(只继承方法签名)、实现继承(继承实际的方法)。
由于函数没有签名,在ECMAScript中无法实现接口继承,只支持实现继承,而实现继承主要是依靠原型链来实现。
原型链基本思路:
利用原型让一个引用类型继承另一个引用类型的属性和方法。
每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针(contructor),而实例对象都包含一个指向原型对象的内部指针(__proto__)。如果让原型对象等于另一个类型的实例,此时的原型对象将包含一个指向另一个原型对象的指针(__proto__),另一个原型对象也包含着一个指向另一个构造函数的指针(constructor)。假如另一个原型又是另一个类型的实例……这就构成了实例与原型的链条。
原型链基本思路(图解):
function Animal()
this.type = "animal";
Animal.prototype.getType = function()
return this.type;
function Dog()
this.name = "dog";
Dog.prototype = new Animal();
Dog.prototype.getName = function()
return this.name;
var xiaohuang = new Dog();
//原型链关系
xiaohuang.__proto__ === Dog.prototype
Dog.prototype.__proto__ === Animal.prototype
Animal.prototype.__proto__ === Object.prototype
Object.prototype.__proto__ === null
Xiaohuang这个Dog的实例对象继承了Animal,Animal继承了Object。
如何理解原型和原型链
每个函数对象都有一个prototype属性(指针),它是一个指向原型对象的指针,原型对象里包含着所有实例共享的属性和方法。同时原型对象里也有一个constructor属性(指针)指回了其对应的构造函数。
每个对象实例都会在其内部初始化一个__proto__属性(指针),它是一个指向prototype(原型对象)的指针,当我们访问一个对象的属性时,如果这个对象内部不存在这个属性,那么他就会通过__proto__去prototype里找这个属性,这个prototype又会有自己的__proto__指向自己的原型对象, 于是就这样一直找下去,形成了原型链的概念。
原型链实现的是对属性的查找,一直顺着原型链查找到Object对象,如果没查到返回undefined,还有值得注意的一点就是,所有对象里的__proto__都是对原型对象的一个引用,而不是副本,所以当我们修改原型时,与之相关的对象也会继承这一改变。
javascript 对象中的 constructor属性的作用?
以上是关于[JS]彻底理解原型链的主要内容,如果未能解决你的问题,请参考以下文章