zoukankan      html  css  js  c++  java
  • __proto__与prototype

    值得一说的是对象没有prototype属性,只有函数有prototype属性。

    var a = function(){};
    a.prototype.d = function(){
        console.log(1);
    }

    prototype相当于给函数a添加了一个属性。

    var a = function(){};
    a.prototype.d = function(){
        console.log(1);
    }
    
    var b = new a();
    b.d(); //1

    用prototype添加的属性,实例化后这个函数的对象也可以继承这个属性。

    那为什么要用prototype添加属性呢?来看看

    var a = function(){
        var f = function(){
            console.log(2);
        }
    };
    
    var b = new a();
    b.f(); //报错

      为什么报错?先看一下call方法和new对象的关系这篇文章,看完你就明白b可以继承函数a的prototype属性了。

      注意我那篇文章只说的了new可以继承prototype属性,但是没有说它可以继承函数里面的内容。所以为什么解决这个为什么我们就会用到prototype了,当然有时为了一些优化的原因也会这样用。

      其实不只是prototype可以解决这个问题,还有this也是可以解决这个问题的,就像我们使用构造函数一样,我们都是用的this对吧,因为new以后就会改变这个this的指向,然后这个属性就会变成你创建出来的那个对象的属性。  对于this的指向问题可以看彻底理解js中this的指向,不必硬背。

    function Fn(){
        this.num = 10;
    }
    var a = new Fn();
    console.log(a.num); //10

      那么__proto__是什么?为了更好的理解__proto__建议你先看什么是作用域链这篇文章。

      __proto__和作用域的行为类似,只不过__proto__是对于对象的属性来说的,而作用域链是对于变量来说的,什么意思?就是说一个对象如果要打印这个对象的某个属性,那么它会先在自己的对象中查找,如果没有找到那么它就会__proto__中找,看看有没有这个属性。那么__proto__中到底有哪些属性?

      你一开始创建的对象__proto__指向了obj.__proto__,也就说明我们创建的任何对象都可以调用obj.__proto__里面的属性和方法,而obj的__proto__为null,也就是说到obj的__proto__就到头了。这也就是说如果我们没有做任何的操作,这个对象只能继承obj.__proto__的属性,这里没有算上obj的__proto__是因为,obj的__proto__为null。

      但是如果我们用了new操作符实例化了一个函数,那么这个new出来的对象就又多了一个继承对象,那就是那个构造函数。而这个构造函数如果用prototype添加属性同样的,这个实例化的对象也可以继承它的属性。

      还有一点就是如果这个对象本身就有这个属性就不会去继承,继承只有在这个对象没有找到的时候才会继承,就和我们学css的继承样式一样。

    function Fn(){
        
    }
    Fn.prototype.num = 10;
    var a = new Fn();
    a.num = 20;
    console.log(a.num); //20

    如果这个对象没有这个属性才会继承,并且这个对象有多个__proto__那么它也只是继承最近的那个属性。

    function Fn(){
        
    }
    Fn.prototype.num = 10;
    var a = new Fn();
    console.log(a.num);

    在这段代码中Fn的__proto__离对象a最近所以继承它的,而不是obj的。

    补充一点:

    function Foo() {};
    var foo = new Foo();
    Foo.prototype.num = 52;
    console.log(foo.num); //52
    console.log(Foo.num); //undefined

    再看

    function Foo() {};
    var foo = new Foo();
    Foo.prototype.num = 52;
    console.log(foo.num); //52
    console.log(Foo.prototype.num); //52

    对,你没有猜错,num只是prototype的属性,而prototype是Foo的属性,自然只能通过Foo.prototype.num来访问这个属性,那么为什么new出来的对象可以不用加prototype就可以访问num呢?

    实际上new出来的对象是这样的。

    var fn = function(a){
        this.a = a;
    }
    var obj = {};
    继承
    obj.__proto__ = fn.prototype;
    改变this指向
    fn.call(obj);

    看到没有,已经写了fn.prototype,自然就可以在后面点那个属性了。ok了吧?

  • 相关阅读:
    PAT 解题报告 1009. Product of Polynomials (25)
    PAT 解题报告 1007. Maximum Subsequence Sum (25)
    PAT 解题报告 1003. Emergency (25)
    PAT 解题报告 1004. Counting Leaves (30)
    【转】DataSource高级应用
    tomcat下jndi配置
    java中DriverManager跟DataSource获取getConnection有什么不同?
    理解JDBC和JNDI
    JDBC
    Dive into python 实例学python (2) —— 自省,apihelper
  • 原文地址:https://www.cnblogs.com/pssp/p/5222075.html
Copyright © 2011-2022 走看看