zoukankan      html  css  js  c++  java
  • 一篇文章搞懂原型、原型链、prototype、__proto__

    在上一讲中,我们简单提到过 prototype 这一抽象化概念,那么在本讲中,我们来具体看一下到底什么是prototype原型,什么是原型链以及大家经常会遇到的问题之prototype/__proto__区别......blablaba

    首先,需要大家明确一个概念 :

    任意一个函数(包括构造函数)都有一个prototype属性,指向该函数的原型对象
    任意一个构造函数实例化的对象,都有一个__proto__属性,指向构造函数的原型对象。
     
    换言之:
    每个构造函数(constructor)都有一个原型对象(prototype),
    原型对象都包含一个指向构造函数的指针,
    而实例(instance)都包含一个指向原型对象的内部指针.
     
    看到这里,是不是有那么一点点绕~~ 下面上代码:
     
    ----------------------------------------------------------    一条分割线,千军万马来相见  (#_ #)  ---------------------------------------------------------
     
    function Father(){
        this.property = true;
    }
    Father.prototype.getFatherValue = function(){
        return this.property;
    }
    function Son(){
        this.sonProperty = false;
    }
    // //继承 Father
    Son.prototype = new Father();//Son.prototype被重写,导致Son.prototype.constructor也一同被重写var instance = new Son();
    alert(instance.getFatherValue());//true

    prototype 和 __proto__ :

    function Person(name,age){
        this.name = name;
        this.age = age;
        this.sex = 'male';
    }
    
    var p1 = new Person('zhangsan','22');
    var p2 = new Person('lisi','22');
    
    console.log(Person.prototype);
    console.log(p1.__proto__)
    console.log(Person.prototype === p1.__proto__)//true
    console.log(p1.__proto__ === p2.__proto__)//true
    
    
    console.log(p1.constructor)//Person构造函数
    console.log(p1.constructor === p2.constructor)//true
    console.log(p1.age === p2.age)//true
    console.log(p1.sex === p2.sex)//true

    new出来的person1对象此时已经和 Person 再无联系了!

    也就是说每一个new出来的实例都有自己的属性和方法的副本,是独立的的!修改其中一个不会影响另一个!此时,我们修改 p1 的 sex 属性值,结果如下:

    p1.sex = 'female';
    console.log(p1.sex);//female
    console.log(p2.sex);//male
     
    现在,我们再次回过头来看刚刚的Person构造函数,
    function Person(name,age){
        this.name = name;
        this.age = age;
        this.sex = 'male';
    }
    var p1 = new Person('zhangsan','22');
    var p2 = new Person('lisi','22');

    我们现在希望构造函数中的 sex 属性是一个共有属性,因为此时用这样的方法,每个实例中都有一个相同的 sex 属性,会造成资源极大的浪费!

    那么原型对象就即将登场了!
    Brendan Eich决定给每一个构造函数都设置一个 prototype 属性,这个属性就指向原型对象。其实原型对象就只是个普通对象,里面存放着所有实例对象需要共享的属性和方法!
     

    所以,我们把需要共享的放到原型对象里,把那些不需要共享的属性和方法存在在构造函数里!
    function Person(name,age){
        this.name = name;
        this.age = age;
    }
    Person.prototype.sex = 'male';
    var p1 = new Person('zhangsan','22'); // p1此时有name,age 两个属性
    var p2 = new Person('lisi','22');
    Person.prototype.home = 'Shanxi';
    console.log(p1.home);
    console.log(p2.home);
    console.log(Person.prototype === p1.__proto__)//true
    js引擎在读取一个实例化后的对象的属性或方法的时候(如p1)先要看这个对象是否具有该属性或方法,
    如果没有,则会继续找它的原型(p1.__proto__),(如上面的例子)
     
    如果有,则找该对象自身的,(如下面的例子),p1找自身的 sex 属性值,而p2要去原型链上找 sex 属性值。
    p1.sex = 'female';   // p1此时有name,age,sex 三个属性,而p2还是只有name,age两个属性
    console.log(p1.sex); // female
    console.log(p2.sex); // male
    function test(name) {
      this.name = name
    }
    test.prototype.getName = function (){
      return this.name
    }
    function test2(){
    
    }
    test2.prototype = new test('lisisi')
    将test2的原型对象的指向改为test的实例对象,
    test2在后续逻辑中就可以通过原型对象prototype继承(访问):
    来自test构造器本身的属性和方法,以及来自test的原型对象prototype的属性和方法

    !!!!!
    如果要访问test2的属性或方法,那么就要去test里面去找,
    但是这些属性和方法在test的构造器constructor内也找不到,
    那么就会顺着test的prototype原型去test.prototype里面去找
    console.log(test2.prototype.constructor)//test函数体,此时并不包括getName方法
    //如果此时test2要访问getName,会通过test的prototype找到getName,因为test2的原型指向了test的实例
    
    
    console.log(test2)
    //test2原本的空的函数体。这说明继承并没有影响它本身的函数,只是改变了函数的prototype指向
    
    var a = new test2();
    console.log(a.getName())//lisisi

    作者:牧羊狼

    出处:https://www.cnblogs.com/edwardwzw/

    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利,谢谢您的配合。 Freedom is not let you do whatever you wanna but teach you not to do the things that you donnot wanna do.

  • 相关阅读:
    中途接手一个项目时候,需要注意
    PPT做交互效果
    hyperledger学习资料
    k8s拾遗
    Day0-3. 部署docker镜像私有仓库harbor
    Day0-2. Docker安装部署
    Day0-1. Docker环境准备
    【转载】轻量级HTTP服务器Nginx(Nginx性能优化技巧)
    使用nginx-module-vts监控各虚拟主机的流量
    Linux系统下终端proxy代理配置
  • 原文地址:https://www.cnblogs.com/edwardwzw/p/11666349.html
Copyright © 2011-2022 走看看