zoukankan      html  css  js  c++  java
  • js原型和原型链,以及__proto__、prototype属性

    __proto__和prototype属性:

    1、__proto__属性:

    在JS里,万物皆对象(函数是对象、原型也是对象...)。对象都具有属性__proto__,这个属性会指向该对象的原型。

    2、prototype属性:

    除此之外,函数(Function)也是对象,而且函数除了上面说的__proto__这个属性外,还有额外的一个prototype属性。函数的 prototype 属性指向了一个对象,这个对象正是调用该构造函数而创建的实例的原型,也就是下面例子中的 person1 和 person2 的原型。

    那什么是原型呢?你可以这样理解:每一个JavaScript对象(null除外)在创建的时候就会与之关联另一个对象,这个对象就是我们所说的原型,每一个对象都会从原型"继承"属性。

    原型链:

    1、函数和原型关系:

    我们先使用构造函数创建一个对象,Person 就是一个构造函数(注:首字母大写只是约定俗成,不大写照样可以),我们使用 new 创建了两个实例对象 person1和persion2。

    function Person() {
     
    }
     
    // prototype是函数才会有的属性
    Person.prototype.name = 'Kevin';
    var person1 = new Person();
    var person2 = new Person();
    console.log(person1.name) // Kevin
    console.log(person2.name) // Kevin

    让我们用一张图表示构造函数和实例原型之间的关系:

     

    在这张图中我们用 Object.prototype 表示实例原型。(构造)函数有一个prototype属性,指向了实例原型。

    2、实例和原型关系:

    那么我们该怎么表示实例与实例原型,也就是 person 和 Person.prototype 之间的关系呢?很自然,我们知道没有对象都有__proto__属性,而且他指向的就是对象的原型。

    function Person() {
     
    }
    var person = new Person();
    console.log(person.__proto__ === Person.prototype); // true

    3、构造函数:

    既然实例对象和构造函数都可以指向原型,那么原型是否有属性指向构造函数或者实例呢?指向实例倒是没有,因为一个构造函数可以生成多个实例,但是原型指向构造函数倒是有的,如下代码可以验证

    function Person() {
    }
    console.log(Person === Person.prototype.constructor); // true

    讲到这里,我们知道了函数、对象实例和原型之间的关系了,他们是通过prototype和__proto__两个属性联系起来的。如下图

     

    4、原型链:

    原型链就是依托__proto__和prototype连接起来的一个原型链条,我们先看个例子

    function Person() {
    }
    // 原型属性
    Person.prototype.name = ‘Jiang’
    var person1 = new Person()
    // 实例属性
    person1.name = ‘J’
    console.log(person1.name) // J

    上面代码中在实例属性和原型属性都有一个名为name的属性,但是最后输出来的是实例属性上的值。

    当我们读取一个属性的时候,如果在实例属性上找到了,就读取它,不会管原型属性上是否还有相同的属性,这其实就是属性屏蔽,即当实例属性和原型属性拥有相同名字的时候,实例属性会屏蔽原型属性,记住只是屏蔽,不会修改,原型属性那个值还在;但是如果在实例属性上没有找到的话,就会在实例的原型上去找,如果原型上还没有,就继续到原型的原型上去找,直到尽头。

    这个尽头是啥?由于原型也是对象,所以也会有__proto__属性,也就是原型的原型;最后就可以找到Object.prototype这个大boss,所有原型对象都是Object构造函数生成的(Object.prototype值为null)。正是因为所有的原型最终都会指向Object.prototype,所以对象的很多方法其实都是继承于此,比如toString()、valueOf(),前面用到的hasOwnProperty,甚至是.constructor、proto

    补充:一些常用方法:

    1)检查对象是否有该属性:

    function Person() {
    }
    var person1 = new Person()
    // 实例属性
    person1.name = ‘J’
    person1.hasOwnProperty(‘name’)  // true

    注:hasOwnProperty属性只有存在于实例中才会返回true

    2)in则会遍历所有属性,不管是实例上的,还是原型上的:

    function Person() {
    }
    Person.prototype.age = ‘100var person1 = new Person()
    person1.name = ‘J’
     
    'name' in person1 // true
    'age' in person1  // true
     
    for (var prop in person1) { 
            console.log(prop)  // name age
    }

    ---------------------
    作者:赶路人儿
    来源:CSDN
    原文:https://blog.csdn.net/liuxiao723846/article/details/81984357 

  • 相关阅读:
    c++实验9 图及图的操作实验
    Html/CSS 示例演练 图书馆后台界面
    c++实验8 哈夫曼编码-译码器
    Html/CSS 初步介绍html和css部分重要标签
    c++实验7 二叉树
    JavaWeb -学生信息管理实践(JDBC+web+三层架构+DBUtil构造思路)
    java 实验6 图形用户界面设计试验(2)
    操作表与操作表数据行
    数据表操作练习
    数据库的介绍:
  • 原文地址:https://www.cnblogs.com/ryelqy/p/10997332.html
Copyright © 2011-2022 走看看