JavaScript中的原型prototype和__proto__的区别及原型链概念
问题
初学js的同学,总是搞不清楚js中的原型是什么东西,看着控制台打印出来的一串串__proto__,迷惑不已。
例如我定义一个Person,创建一个实例p,并打印实例。
function Person(){}
var p = new Person();
console.log(p)
图中,打印出来一个Person的实例对象p,
这个对象有个__proto__ 属性,这个是什么东西?
__proto__属性下又有constructor属性和__proto__属性。
constructor是什么,为什么打印结果是 Person()?
另外一个__proto__是什么?
为了解答上边的问题,我们需要了解一些相关概念。
一、原型
prototype
首先,说明一下,JS中,万物皆对象。
每个函数对象都有一个属性prototype(函数对象特有属性),这个属性是一个引用,指向一个对象,这个对象的作用就是包含所有实例共享的属性和方法。我们把这个对象就叫做原型对象,也叫显式原型。
__proto__
每个对象都有一个属性__proto__,也可称为隐式原型,对象的隐式原型指向创建该对象的构造函数的原型(prototype)。
constructor
函数的原型对象有一个constructor属性,这个属性是一个引用,用于指向原构造函数。
关系
我们怎么理解上边的概念,而它们之间又有什么联系呢?
我们不妨打印出来p.__proto__属性:
可以看到,打印出来是一个对象,对象里边有个属性constructor。
constructor是什么呢,打印如下:
可以看到,打印出来是函数,代表的就是Person构造函数本身.
再依次打印出来Person构造函数的原型Person.prototype,
和其原型的属性constructor:
从上图我们就可以得出:
1.实例对象p有属性__proto__ 指向的就是创建它的构造函数的原型对象Person.prototype。
2.构造函数的原型对象Person.prototype的属性constructor指向Person构造函数本身。
我们可以验证一下:
但是,可能又有些同学有疑惑了,那既然所有对象都有__proto__属性,
那构造函数Person()的属性__proto__指向谁呢?
当然是指向它的构造函数的原型对象了。
函数的构造函数就是Function(),因此这里的__proto__指向Function.prototype。
那原型对象也是对象,它的__proto__属性指向谁呢?
同理,指向它的构造函数的原型对象,即Object.prototype。
这里,我们就不得不提一下,原型链的概念了。
原型链
原型链是一种机制,指的是js中,每个对象都有一个属性__proto__,指向它的构造函数的原型对象。原型对象也是一个对象,因此也有__proto__属性指向原型对象的原型对象,这样一层层向上直到对象的原型对象为空(Object的原型对象Object.prototpye的属性__proto__为null)。
因此,例子中原型链的关系如下:
p.__proto__ 指向 Person.prototype,
Person.prototype.__proto__指向的就是Object.prototype,
Object.prototpye.__proto__ 指向null
为了理解上边例子的原型链关系,我们画一张图来增加理解:
至此,上边的问题是不是心里已经有答案了呢。
总结
1.每个对象都有一个__proto__属性,指向创建它的构造函数的原型对象。
作用:构成原型链,用于实现基于原型的继承。
2.函数除了有__proto__属性,还有一个prototype属性,用来指向函数的原型对象。
作用:用于实现基于原型的继承和属性共享。
因此,你会在很多地方见到有类似这样的写法:
function Person(){}
Person.prototype.hello = function(){
console.log("hello")
}
上边代码表示,所有Person创建的实例对象都可以共享hello方法。
3.构造函数的原型对象有属性constructor,指向构造函数本身。
PS:欢迎关注公众号:「如若清风」,一起交流学习。
JavaScript中的原型prototype和__proto__的区别及原型链概念的更多相关文章
- javascript的构造函数和实例对象、prototype和__proto__的区别,原型对象及构造器的理解
一.前言 我们先通过代码来分别打印出实例对象.构造函数,以及修改了原型对象的构造函数,通过对比内部结构来看看他们之间的区别. //定义构造函数 function Person(name, age){ ...
- JS 中的原型 -- prototype、__proto__ 以及原型链
原文: 1.深入理解javascript原型和闭包——prototype原型 2.三张图搞懂JavaScript的原型对象与原型链 打开浏览器控制台,任意定义一个对象,打印出来后,会发现有最后一定有一 ...
- 前端开发:面向对象与javascript中的面向对象实现(二)构造函数与原型
前端开发:面向对象与javascript中的面向对象实现(二)构造函数与原型 前言(题外话): 有人说拖延症是一个绝症,哎呀治不好了.先不说这是一个每个人都多多少少会有的,也不管它究竟对生活有多么大的 ...
- JavaScript中的Array.prototype.slice.call()方法学习
JavaScript中的Array.prototype.slice.call(arguments)能将有length属性的对象转换为数组(特别注意: 这个对象一定要有length属性). 但有一个例外 ...
- javascript中apply、call和bind的区别,容量理解,值得转!
a) javascript中apply.call和bind的区别:http://www.cnblogs.com/cosiray/p/4512969.html b) 深入浅出 妙用Javascrip ...
- javascript中三目运算符和if else有什么区别
javascript中三目运算符和if else有什么区别今天写了一个图片轮播的小demo,用到了判断先试了一下if else,代码如下:if(n >= count-1){n =0;}else{ ...
- JavaScript中var和this定义变量的区别
JavaScript中var和this定义变量的区别 在js中声明变量时可以使用var和this,但使用this的有很大一部分参考书是没有的,经过查阅相关资料总结如下: 用var和this声明变量,存 ...
- javascript中back(-1)和go(-1)的区别
javascript中back(-1)和go(-1)的区别 一.总结 一句话总结: 数据 history.back(-1):直接返回当前页的上一页,数据全部消息,是个新页面 history.go(-1 ...
- JavaScript中基本数据类型和引用数据类型的区别(栈——堆)
JavaScript中基本数据类型和引用数据类型的区别 1.基本数据类型和引用数据类型 ECMAScript包括两个不同类型的值:基本数据类型和引用数据类型. 基本数据类型指的是简单的数据段,引用数据 ...
随机推荐
- android 自己制作Jar包 和 修改 现成的 Jar包文件
先看如何创建自己的 Jar 包 里面随便写个方法 public int add(int a,int b){ return (a+b); } task makeJar(type: Copy) { del ...
- 机器学习---朴素贝叶斯与逻辑回归的区别(Machine Learning Naive Bayes Logistic Regression Difference)
朴素贝叶斯与逻辑回归的区别: 朴素贝叶斯 逻辑回归 生成模型(Generative model) 判别模型(Discriminative model) 对特征x和目标y的联合分布P(x,y)建模,使用 ...
- PKUWC2019 Round 2 没去祭
因为今年有两场 PKUWC,所以叫 PKUWC2019 Round 2. 因为一些沙雕原因,今年去不了了. Day 0 一如既往,没有集训就去上数学课,今天讲几何变换,一如既往的只会说"少女 ...
- jmap -heap 查看堆内存
概述 用jmap -heap命令可以查看linux堆内存分布 具体用法 1:先查出tomcat的进程号 例如: 然后执行 jmap -heap 7095 可以打印出整体的堆信息 可以看到经过分配的 ...
- 安装OpenStack Queens版本的教程推荐
为了加深对OpenStack的理解,需要自己分模块安装一次,之前都是用devstack安装,傻瓜式安装虽然方便,但是也减少了我对OpenStack理解的深度. 本人参考如下文档安装成功过 http:/ ...
- solr 使用
Solr安装 1:安装 Tomcat,解压缩即可. 2:解压 solr. 3:把 solr 下的dist目录solr-4.10.3.war部署到 Tomcat\webapps下(去掉版本号). 4:启 ...
- Beta3冲刺
队名:福大帮 组长博客链接: 作业博客 : https://edu.cnblogs.com/campus/fzu/SoftwareEngineeringClassAofFuzhouUniversity ...
- .sql文件l通过PLSQL导入到Oracle数据库
最近从第三方共享到一个数据,对方提供的是.sql文件.如何导入Oracle数据库? 开始想通过navicat for mysql工具--运行SQL文件来导入表---总是出现错误,失败. 后来还是用回P ...
- 000 list与map的foreach使用
一:list的使用 1.程序 package com.jun.it.java8; import java.util.ArrayList; import java.util.List; public c ...
- 使用nodejs+http(s)+events+cheerio+iconv-lite爬取2717网站图片数据到本地文件夹
源代码如下: //(node:9240) Warning: Setting the NODE_TLS_REJECT_UNAUTHORIZED environment variable to '0' ...