在开始先给出我在知乎上看到的一张图,可以帮助理解: 如果现在你还不能很好的理解这副图的意思,那请继续往下看。 一、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 say p.writeCode(); // Programmer writes code console.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现在我们再回头看最开始的那副图,应该就能理解了。