阐述JS中原型链及prototype和__proto__的区别

来源:互联网 发布:鲍登学院 知乎 编辑:程序博客网 时间:2024/05/18 02:08

在开始先给出我在知乎上看到的一张图,可以帮助理解:
这里写图片描述
如果现在你还不能很好的理解这副图的意思,那请继续往下看。
一、prototype和 _proto_ 的概念
prototype是函数的一个属性(每个函数都有一个prototype属性),这个属性是一个指针,指向一个对象。它是显示修改对象的原型的属性。
_ proto_ 是一个对象拥有的内置属性(请注意:prototype是函数的内置属性,_ proto_ 是对象的内置属性),_ proto_ 是JS内部使用寻找原型链的属性。简单来说,在 javascript 中每个对象都会有一个 _ proto _ 属性,当我们访问一个对象的属性时,如果这个对象内部不存在这个属性,那么他就会去 _ proto _ 里找这个属性,这个 _ proto _ 又会有自己的 _ proto _,于是就这样一直找下去,也就是我们平时所说的原型链的概念.
用chrome和FF都可以访问到对象的_ proto _属性,IE不可以。
二、new 的过程

var Person = function(){};var p = new Person();//*new的过程拆分成以下三步:*//(1) var p={}; 也就是说,初始化一个对象p;//(2) p. __ proto __ = Person.prototype;//(3) Person.call(p); 也就是说构造p,也可以称之为初始化p

关键在于第二步,我们来证明一下

var Person = function(){};var p = new Person();alert(p.__proto__ === Person.prototype);

这段代码会返回true。说明我们步骤2是正确的。

三、示例

var Person = function(){};Person.prototype.sayName = function() {    alert("My Name is Jacky");};Person.prototype.age = 27;var p = new Person();p.sayName();

p是一个引用指向Person的对象。我们在Person的原型上定义了一个sayName方法和age属性,当我们执行p.sayName( )时,会先在this的内部查找(也就是构造函数内部),如果没有找到然后再沿着原型链向上追溯。
这里的向上追溯是怎么向上的呢?这里就要使用_ proto _属性来链接到原型(也就是Person.prototype)进行查找。最终在原型上找到了age属性。
接下来,让我们看个更复杂的代码。

var Person = function() {};Person.prototype.say = function() {    console.log("Person say");}Person.prototype.salary = 50000;var Programmer = function() {};Programmer.prototype = new Person();Programmer.prototype.writeCode = function() {    console.log("Programmer writes code");};Programmer.prototype.salary = 500;var p = new Programmer();p.say();    // Person sayp.writeCode();  // Programmer writes codeconsole.log(p.salary); // 500// 推导过程一 --> // Programmer.prototype = {};// Programmer.prototype.__proto__ = Person.prototype;// Person.call(Programmer.prototype);// 推导过程二 --> // var p = {};// p.__proto__ = Programmer.prototype;// p.__proto__ = new Person();// p.__proto__.__proto__ = Pserson.prototype;// Person.call(p.__proto__);// Programmer.call(p);

当我们调用 p.say() 时,p 中是没有 say 属性,于是到 p 的 _ proto _ 属性中去找,也就是 Programmer.prototype,此时 Programmer.prototype 是等于 new Person(),但 new Person() 中也没有 say 属性,于是又到 new Person()._ proto _ 中找,此时 new Person()._ proto _ 等于 Pserson.prototype 的,我们定义了 Person.prototype.say=function(){}; 所以,p 在 Person.prototype 中就找到了这个方法。
过程:

p –> p.__proto__ === Programmer.prototype === new Person() –> p.__proto__.__proto__ === Programmer.prototype.__proto__ === new Person().__proto__ === Pserson.prototype

现在我们再回头看最开始的那副图,应该就能理解了。

原创粉丝点击