Js中 constructor, prototype, __proto__ 详解

Souleigh ✨ 等级 679 0 0
标签: js前端

本文为了解决以下问题:

__proto__(实际原型)和prototype(原型属性)不一样!!! constructor属性(原型对象中包含这个属性,实例当中也同样会继承这个属性) prototype属性(constructor.prototype原型对象) __proto__属性(实例指向原型对象的指针)

首先弄清楚几个概念:

什么是对象? 若干属性的集合

什么是原型? 原型是一个对象,其他对象可以通过它实现继承。

哪些对象有原型? 所有的对象在默认情况下都有一个原型,因为原型本身也是对象,所以每个原型自身又有一个原型(只有一种例外,默认的对象原型在原型链的顶端) 任何一个对象都可以成为原型

接下来就是最核心的内容:

constructor 属性

constructor属性始终指向创建当前对象的构造函数。

    var arr=[1,2,3];
    console.log(arr.constructor); //输出 function Array(){}
    var a={};
    console.log(arr.constructor);//输出 function Object(){}
    var bool=false;
    console.log(bool.constructor);//输出 function Boolean(){}
    var name="hello";
    console.log(name.constructor);//输出 function String(){}
    var sayName=function(){}
    console.log(sayName.constrctor)// 输出 function Function(){}

    //接下来通过构造函数创建instance
    function A(){}
    var a=new A();
    console.log(a.constructor); //输出 function A(){}

以上部分即解释了任何一个对象都有constructor属性,指向创建这个对象的构造函数.

prototype属性

注意:prototype是每个函数对象都具有的属性,被称为原型对象,而proto属性才是每个对象才有的属性。一旦原型对象被赋予属性和方法,那么由相应的构造函数创建的实例会继承prototype上的属性和方法。

    //constructor : A
    //instance : a
    function A(){}
    var a=new A();

    A.prototype.name="xl";
    A.prototype.sayName=function(){
        console.log(this.name);
    }

    console.log(a.name);// "xl"
    a.sayName();// "xl"

    //那么由constructor创建的instance会继承prototype上的属性和方法

constructor属性和prototype属性

每个函数都有prototype属性,而这个prototype的constructor属性会指向这个函数。

    function Person(name){
        this.name=name;
    }
    Person.prototype.sayName=function(){
        console.log(this.name);
    }

    var person=new Person("xl");

    console.log(person.constructor); //输出 function Person(){}
    console.log(Person.prototype.constructor);//输出 function Person(){}
    console.log(Person.constructor); //输出 function Function(){}

如果我们重写(重新定义)这个Person.prototype属性,那么constructor属性的指向就会发生改变了。

    Person.prototype={
        sayName:function(){
            console.log(this.name);
        }
    }

    console.log(person.constructor==Person); //输出 false (这里为什么会输出false后面会讲)
    console.log(Person.constructor==Person); //输出 false

    console.log(Person.prototype.constructor);// 输出 function Object(){}  
    //这里为什么会输出function Object(){}
    //还记得之前说过constructor属性始终指向创建这个对象的构造函数吗?

    Person.prototype={
        sayName:function(){
            console.log(this.name);
        }
    }
    //这里实际上是对原型对象的重写:
    Person.prototype=new Object(){
        sayName:function(){
            console.log(this.name);
        }
    }
    //看到了吧。现在Person.prototype.constructor属性实际上是指向Object的。

    //那么我如何能将constructor属性再次指向Person呢?
    Person.prototype.constructor=Person;

接下来解释为什么,看下面的例子。

    function Person(name){
        this.name = name;
    } 
    var personOne=new Person("xl"); 
    Person.prototype = {
        sayName: function(){
            console.log(this.name);
        }
    };
    var personTwo = new Person('XL');
    console.log(personOne.constructor == Person); //输出true
    console.log(personTwo.constructor == Person); //输出false   
    //大家可能会对这个地方产生疑惑?为何会第二个会输出false,personTwo不也是由Person创建的吗?这个地方应该要输出true啊?
    //这里就涉及到了js里面的原型继承
    //这个地方是因为person实例继承了Person.prototype原型对象的所有的方法和属性,包括constructor属性。当Person.prototype的constructor发生变化的时候,相应的person实例上的constructor属性也会发生变化。所以第二个会输出false;
    //当然第一个是输出true,因为改变构造函数的prototype属性是在personOne被创建出来之后。

proto和prototype属性

    function Person(name){
        this.name=name;
    }
    Person.prototype.sayName=function(){
        console.log(this.name);
    }
    var person=new Person("xl");
    person.sayName(); //输出 "xl"

    //constructor : Person
    //instance : person

首先给构造函数的原型对象Person.prototype赋给sayName方法,由构造函数Person创建的实例person会继承原型对象上的sayName方法。

为什么会继承原型对象的方法?

因为ECMAscript的发明者为了简化这门语言,同时又保持继承性,采用了链式继承的方法。 由constructor创建的每个instance都有个__proto__属性,它指向constructor.prototype。那么constrcutor.prototype上定义的属性和方法都会被instance所继承。

    function Person(name){
        this.name=name;
    }
    Person.prototype.sayName=function(){
        console.log(this.name);
    }

    var personOne=new Person("a");
    var personTwo=new Person("b");

    personOne.sayName(); // 输出  "a"
    personTwo.sayName(); //输出 "b"

    console.log(personOne.__proto__==Person.prototype); // true
    console.log(personTwo.__proto__==Person.prototype); // true

    console.log(personOne.constructor==Person); //true
    console.log(personTwo.constructor==Person); //true
    console.log(Person.prototype.constructor==Person); //true

    console.log(Person.constructor); //function Function(){}
    console.log(Person.__proto__.__proto__);
收藏
评论区

相关推荐

Js中 constructor, prototype, __proto__ 详解
本文为了解决以下问题: __proto__(实际原型)和prototype(原型属性)不一样!!! constructor属性(原型对象中包含这个属性,实例当中也同样会继承这个属性) prototype属性(constructor.prototype原型对象) __proto__属性(实例指向原型对象的指针) <br/ 首先弄清楚几个概念: <br/
彻底搞懂 JS 中的 prototype、__proto__与constructor
1\. 前言作为一名前端工程师,必须搞懂JS中的prototype、proto与constructor属性,相信很多初学者对这些属性存在许多困惑,容易把它们混淆,本文旨在帮助大家理清它们之间的关系并彻底搞懂它们。这里说明一点,proto属性的两边是各由两个下划线构成(这里为了方便大家看清,在两下划线之间加入了一个空格: proto ,读作“dunder pr
nodom2
nodom2 主要完成了常见js表达式处理包括 操作符 ()!|\*/+-><=&%,以及操作符组合如>=、===、!== 等,值null undefined true false。 代码结构有了很大优化,字符串处理变得更简单,分为字符串、变量和函数。 代码如下: class Expression{ /** * @para
ES6箭头函数特点
### 1、语法简单 const fun=x=>1; const fun=()=>1; const fun=(x,y)=>{1;return x+y;} ### 2、内置return语句、单行代码返回当前代码的返回值、多行时返回undefined ### 3、自动绑定this、this为上级的作用域
JS原型、原型链深入理解
**原型**是JavaScript中一个比较难理解的概念,原型相关的属性也比较多,对象有”prototype”属性,函数对象有”prototype”属性,原型对象有”constructor”属性。 **原型**是JavaScript中一个比较难理解的概念,原型相关的属性也比较多,对象有”prototype”属性,函数对象有”prototype”属性,原型对
241个jquery插件—jquery插件大全
**jQuery**由美国人John Resig创建,至今已吸引了来自世界各地的众多javascript高手加入其team. jQuery是继prototype之后又一个优秀的Javascrīpt框架。其经典的Slogan是**“Write Less, Do more”(写更少的代码,做更多的事情)**。jQuery是轻量级的js库(压缩后只有21k) ,这
23.JavaScript原型和原型链
1.原型:prototype,所有的函数都有一个属性prototype,称之为函数原型 默认情况下,prototype是一个普通的Object对象 默认情况下,prototype中有一个属性constructor,它也是一个对象,它指向构造函数本身 function Test(){} Test.prototype:函数Test的原型 Test.pr
JS中popup.js
//popup class 显示弹出窗口,。 /\*以下为使用popup对象,传入相应的配置参数,弹出不同类型的窗口          function ShowIframe() //显示iframe          {              var pop=new Popup({ contentType:1,isReloadOnClo
JS前端图形化插件之利器Gojs组件(php中文网)
JS前端图形化插件之利器Gojs组件(php中文网) ========================== 一、总结 ---- ### 一句话总结:php中文网我可以好好走一波 二、JS前端图形化插件之利器Gojs组件 -------------------- 参考: JS前端图形化插件之利器Gojs组件-js教程-PHP中文网 http://
JavaScaript学习笔记第(一)
js由三部分组成,分别是ECMAScript、DOM、BOM 其中ECMAScript规定了js的语法 js是一门解释型语言、脚本语言、动态类型语言、基于对象语言 书写js代码和CSS一样,有三个书写的地方,第一个是使用<script>标签,再<sccript>标签中书写js代码,标签一般都在body标签中的末尾,第二个地方是书写再结构里,html标签
JavaScript 两个叹号含义
先起个例子吧~  这个用的是谋智的js引擎monkey spider  darion.yaphet@localhost.localdomain:/home/darion.yaphet> js               js> var i; js> print(i) undefined js>  js> va
JavaScript八张思维导图
**![](https://oscimg.oschina.net/oscnet/17104907-a0f0-4b40-ac9d-9c40d9b13157.jpg)** **目录** * JS基本概念 * JS操作符 * JS基本语句 * JS数组用法 * Date用法 * JS
JavaScript基础之原型
![](https://oscimg.oschina.net/oscnet/ff99d8a2-0991-4597-91c1-3e05dcc12e19.png) ![](https://oscimg.oschina.net/oscnet/046cfb95-612c-4235-81bb-3e09a300ea43.jpg) JS中每个函数都可以看成一个对象,而
Javascript 是如何体现继承的 ?
js继承的概念 js里常用的如下两种继承方式: 原型链继承(对象间的继承) 类式继承(构造函数间的继承)   由于js不像java那样是真正面向对象的语言,js是基于对象的,它没有类的概念。所以,要想实现继承,可以用js的原型prototype机制或者用apply和call方法去实现 在面向对象的语言中,我们使用类来创建一个自定义对象