zoukankan      html  css  js  c++  java
  • 阐述JS中原型链及prototype和__proto__的区别

    在开始先给出我在知乎上看到的一张图,可以帮助理解:

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

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

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

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

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

    三、示例

    1 var Person = function(){};
    2 Person.prototype.sayName = function() {
    3     alert("My Name is Jacky");
    4 };
    5 
    6 Person.prototype.age = 27;
    7 var p = new Person();
    8 p.sayName();

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

     1 var Person = function() {};
     2 Person.prototype.say = function() {
     3     console.log("Person say");
     4 }
     5 Person.prototype.salary = 50000;
     6 
     7 var Programmer = function() {};
     8 Programmer.prototype = new Person();
     9 Programmer.prototype.writeCode = function() {
    10     console.log("Programmer writes code");
    11 };
    12 Programmer.prototype.salary = 500;
    13 
    14 var p = new Programmer();
    15 p.say();    // Person say
    16 p.writeCode();  // Programmer writes code
    17 console.log(p.salary); // 500
    18 
    19 // 推导过程一 --> 
    20 // Programmer.prototype = {};
    21 // Programmer.prototype.__proto__ = Person.prototype;
    22 // Person.call(Programmer.prototype);
    23 // 推导过程二 --> 
    24 // var p = {};
    25 // p.__proto__ = Programmer.prototype;
    26 // p.__proto__ = new Person();
    27 // p.__proto__.__proto__ = Pserson.prototype;
    28 // Person.call(p.__proto__);
    29 // 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 中就找到了这个方法。
    过程:

    1 p –> 
    2 p.__proto__ === Programmer.prototype === new Person() –> 
    3 p.__proto__.__proto__ === Programmer.prototype.__proto__ === new Person().__proto__ === Pserson.prototype
  • 相关阅读:
    axios解决调用后端接口跨域问题
    vuex的使用入门-官方用例
    vue使用axios实现前后端通信
    vue组件间通信用例
    vue-router的访问权限管理
    vue-router使用入门
    PHP 流程控制
    PHP 表达式和运算符
    PHP 预定义变量
    PHP 常量
  • 原文地址:https://www.cnblogs.com/zlq92/p/10178286.html
Copyright © 2011-2022 走看看