问题

初学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__的区别及原型链概念的更多相关文章

  1. javascript的构造函数和实例对象、prototype和__proto__的区别,原型对象及构造器的理解

    一.前言 我们先通过代码来分别打印出实例对象.构造函数,以及修改了原型对象的构造函数,通过对比内部结构来看看他们之间的区别. //定义构造函数 function Person(name, age){ ...

  2. JS 中的原型 -- prototype、__proto__ 以及原型链

    原文: 1.深入理解javascript原型和闭包——prototype原型 2.三张图搞懂JavaScript的原型对象与原型链 打开浏览器控制台,任意定义一个对象,打印出来后,会发现有最后一定有一 ...

  3. 前端开发:面向对象与javascript中的面向对象实现(二)构造函数与原型

    前端开发:面向对象与javascript中的面向对象实现(二)构造函数与原型 前言(题外话): 有人说拖延症是一个绝症,哎呀治不好了.先不说这是一个每个人都多多少少会有的,也不管它究竟对生活有多么大的 ...

  4. JavaScript中的Array.prototype.slice.call()方法学习

    JavaScript中的Array.prototype.slice.call(arguments)能将有length属性的对象转换为数组(特别注意: 这个对象一定要有length属性). 但有一个例外 ...

  5. javascript中apply、call和bind的区别,容量理解,值得转!

    a)  javascript中apply.call和bind的区别:http://www.cnblogs.com/cosiray/p/4512969.html b)  深入浅出 妙用Javascrip ...

  6. javascript中三目运算符和if else有什么区别

    javascript中三目运算符和if else有什么区别今天写了一个图片轮播的小demo,用到了判断先试了一下if else,代码如下:if(n >= count-1){n =0;}else{ ...

  7. JavaScript中var和this定义变量的区别

    JavaScript中var和this定义变量的区别 在js中声明变量时可以使用var和this,但使用this的有很大一部分参考书是没有的,经过查阅相关资料总结如下: 用var和this声明变量,存 ...

  8. javascript中back(-1)和go(-1)的区别

    javascript中back(-1)和go(-1)的区别 一.总结 一句话总结: 数据 history.back(-1):直接返回当前页的上一页,数据全部消息,是个新页面 history.go(-1 ...

  9. JavaScript中基本数据类型和引用数据类型的区别(栈——堆)

    JavaScript中基本数据类型和引用数据类型的区别 1.基本数据类型和引用数据类型 ECMAScript包括两个不同类型的值:基本数据类型和引用数据类型. 基本数据类型指的是简单的数据段,引用数据 ...

随机推荐

  1. 桥接:JS调用安卓方法报错Uncaught Error: Error calling method on NPObject

    说一说自己粗心踩到的一个不算坑的坑: 项目是安卓webview嵌入SPA单页应用页面,涉及到JS调用原生安卓方法,但就是在调用安卓方法时死活一直报错xxx  NPObject一堆错误.写了一个测试页面 ...

  2. HTML5之contenteditable可编辑属性

    运用contenteditable实现输入框高度自动增加,输入框标题name相对高度自动居中,代码如下: <!DOCTYPE html> <html> <head> ...

  3. session使用方法

    每次客户端检索网页时,都要单独打开一个服务器连接,因此服务器不会记录下先前客户端请求的任何信息. 如何维持客户端与服务器的会话?方法之一: servlet中写入: //新建一个session保存用户名 ...

  4. Tcl条件语句

    If {条件表达式1} { 执行语句1 } elseif {条件表达式2} { 执行语句2 } elseif {条件表达式3} { 执行语句3 } else { 执行语句4 } 注:elseif {条 ...

  5. ICEM-圆角正方体

    原视频下载地址:https://pan.baidu.com/s/1c2cNgJm 密码: rci8

  6. rust结构体

    //Rust 并不允许只将某个字段标记为可变 struct User { email: String, name:String, age:i32, sex:String, active:bool, } ...

  7. [BUAA软工]团队任务拆解

    团队任务分解 本次博客为项目alpha的任务拆解 WBS 任务估计 任务 时长(h) 语音模块:监听部分 5h 语音模块:消息处理:api 4h 语音模块:消息处理:内部数据结构 3h 语音模块:消息 ...

  8. JAVA学习网站分享

    好久没用博客园了 最近工作不忙了,可以花时间自己学习知识提升自己,所以开始查找各种资料 java资源查找网站:           http://www.java1234.com/ 前端学习网站:  ...

  9. 第07组 Alpha冲刺(5/6)

    队名:摇光 队长:杨明哲 组长博客:求戳 作业博客:求再戳 队长:杨明哲 过去两天完成了哪些任务 文字/口头描述:依然在完善网页编辑器的后端. 展示GitHub当日代码/文档签入记录:(组内共用,已询 ...

  10. SQLServer replace函数

    declare @name char(1000) --注意:char(10)为10位,要是位数小了会让数据出错 set @name='ssssfcfgghdghdfcccs' select repla ...