js高级——构造函数,实例对象和原型对象——prototype、__proto__和constructor构造器
一、前言
了解JavaScript面向对象,需要先了解三个名词: 构造函数,实例对象和原型对象。
注意:JavaScript中没有类(class)的概念,取而代之的是构造函数,两者类似却又有很大的差别。
先上代码,最常用的:
function Person(name, age) {
this.name = name;
this.age = age;
this.eat= function() { alert('吃西红柿') }
}
var person1 = new Person('小米', 28);
var person2 = new Person('大米', 23);
Chrome打印测试,上图:



上图分别是:
- 图一打印perspn1实例对象,
- 图二打印Person构造函数,
- 图三打印构造函数的prototype(即Person的原型对象)和person1的__proto__
通过上面的打印,我们可以发现几个问题:
- 实例对象和构造函数一点也不像,
- person1.__proto__和Person.prototype一模一样
我们先来看看第一个问题:实例对象和它的构造函数——打印出来的内容一点也不像

这个问题就大了呀!
我们都知道,在java中,类和它的实例对象之间有很紧密的关系,你的(属性和方法)是我的,我的还是我的!
可是到了js这里,Person构造函数中并没有体现出他本该有的属性和方法
也就是说,无论我们实例化出来多少个person,他们的属性和方法都是不一样的。属性不一样还可以理解,方法不一样就意味着:每个实例出来的person的方法并不是共用的(并不指向同一个地址空间),那我们要构造函数还有什么意义?
我们要的还是类和实例对象的关系那样,能够共享数据,节省内存空间
这就引出了我们今天要讲的关键:原型
二、正文
(一)、使用原型对象造共用属性和方法
前面已经讲到,js的构造函数和实例对象之间,并不能够实现共享数据,节省内存空间的作用,所以我们就引入了原型这一概念
再上代码:这次我们添加了原型方法play()
//构造函数
function Person(name, age) {
this.name = name;
this.age = age;
this.eat= function() { alert('吃西红柿') }
}
//添加原型方法
Person.prototype.play = function() { alert("玩溜溜球")}
//实例化对象
var person1 = new Person('小米', 28);
var person2 = new Person('大米', 23);
在仅限Chrome测试:



上图分别是:
- 图一打印perspn1实例对象,
- 图二打印Person构造函数,
- 图三打印构造函数的prototype(即Person的原型对象)和person1的__proto__

通过上图可以知道:构造函数中定义的方法,实例化后并不一样,而原型对象prototype中定义的方法确实相等的(指向同一地址)
添加了原型方法后,实例对象person1和构造函数Person上并没有直观体现,反而在Person.prototype和person1.__proto__中显示了出来
由此,我们可以知道,JS中给同一构造函数的实例对象 添加共用属性和方法,需要使用prototype这一属性,也就是原型对象来实现
(二)、prototype和__proto__和constructor构造器

上图表现出:Person.prototype === person1.__proto__
即:实例对象的__proto__和构造函数的prototype相等(指向同一地址),完全一样



上图,图一打印Person.prototype;图二打印person1.__proto__;图三打印Person构造函数
通过上面三张图,我们可以发现:Person.prototype.constructor和person1.__proto__.constructor以及Person一模一样

上图表现出:Person.prototype.constructor === Person
即:构造函数的原型对象(prototype)的构造器(constructor)指向该构造函数
通过之前的打印和上图,我们可以发现,
- 实例对象中都有__proto__属性,而构造函数中都有prototype属性,
- prototype和__proto__都有构造器constructor,其实实例对象的__proto__和构造函数的prototype是一样的(Person.prototype === person1.__proto__)
- 构造函数的原型对象(prototype)的构造器(constructor)指向该构造函数(Person.prototype.constructor === Person)
(三)、使用原型的注意事项
原型属性和方法统一定义时,需要定义构造器constructor,即将构造函数的原型对象中的构造器指向该构造函数,否则原型属性和方法定义失败
//添加原型方法
Person.prototype.job= "程序员"
Person.prototype.address = "苏州"
Person.prototype.study= function() { alert("学JavaScript")} //可以这样定义吗?
Person.prototype = {
job: "程序员",
address: "苏州" ,
study: function() { alert("学JavaScript")}
} //上面的原型对象定义出错,需要加上constructor--手动修改构造器的指向
Person.prototype = {
constructor: Person,
job: "程序员",
address: "苏州" ,
study: function() { alert("学JavaScript")}
}
分别将两种添加原型属性和方法的方式打印看看:


上图分别是:
- 图一为错误示范,表示未手动修改构造器指向,结果打印显示Person.prototype丢失构造器constructor,被新添加的对象覆盖
- 图二为正确示范,表示手动修改构造器指向,即加上constructor: Person,
三、结束
加油哦,最后来张图

js高级——构造函数,实例对象和原型对象——prototype、__proto__和constructor构造器的更多相关文章
- 深入理解JavaScript原型:prototype,__proto__和constructor
JavaScript语言的原型是前端开发者必须掌握的要点之一,但在使用原型时往往只关注了语法,其深层的原理并未理解透彻.本文结合笔者开发工作中遇到的问题详细讲解JavaScript原型的几个关键概念, ...
- JS高级---构造函数,实例对象和原型对象,三者关系
构造函数,实例对象和原型对象,三者关系 构造函数里面有原型(prototype)属性,即原型对象 原型对象里的constryctor构造器指向构造函数 通过构造函数,实例化,创建的就是实例对象. 实例 ...
- JS高级---构造函数通过原型添加方法,原型的作用: 共享数据, 节省内存空间
JS高级---构造函数,通过原型添加方法,原型的作用: 共享数据, 节省内存空间 构造函数 //构造函数 function Person(sex, age) { this.sex = sex; thi ...
- 理解javascript 对象,原型对象、闭包
javascript作为一个面向对象的语言,理解 对象.原型.闭包.模块模式等技术点对于成为一名合格的javascript程序员相当重要,多年没写过blog,今天就先拋个玉,在下基本也不做前端,但颇感 ...
- js prototype __proto__ instanceof constructor
JS中有两个特殊的对象:Object与Function,它们都是构造函数,用于生成对象. Object.prototype是所有对象的祖先,Function.prototype是所有函数的原型,包括构 ...
- JS核心系列:浅谈原型对象和原型链
在Javascript中,万物皆对象,但对象也有区别,大致可以分为两类,即:普通对象(Object)和函数对象(Function). 一般而言,通过new Function产生的对象是函数对象,其他对 ...
- 关于Javascript中通过实例对象修改原型对象属性值的问题
Javascript中的数据值有两大类:基本类型的数据值和引用类型的数据值. 基本类型的数据值有5种:null.undefined.number.boolean和string. 引用类型的数据值往大的 ...
- 对ES6中类class以及实例对象、原型对象、原型链之间关系的详细总结
1. 类 ES6 中新增加了类的概念,可以使用 class 关键字声明一个类,之后用这个类来实例化对象.即类的用途:实例化对象. // 创建一个Person类 class Person { } // ...
- jQuery的核心对象、原型对象、静态方法、动态方法
什么叫jQuery的核心对象? $ $===jQuery 什么叫jQuery的原型对象? $.fn $.fn===$.prototype 什么叫静态方法? 在构造函树上定义的方法,静态方法通过构造函数 ...
随机推荐
- myeclipse web servelet调试输入的中文在TOMCAT服务器的命令行显示为????
B 问题:myeclipse web servelet调试输入的中文在TOMCAT服务器的命令行显示为???? 解决:调整JSP页面编码:gb2312--->utf-8
- UOJ117. 欧拉回路【欧拉回路模板题】
LINK 题目大意 就是让你对有向图和无向图分别求欧拉回路 非常的模板,但是由于UOJ上毒瘤群众太多了 所以你必须加上一个小优化 就是每次访问过一个边就把它删掉 有点像Dinic的当前弧优化的感觉 注 ...
- .NET/C# 判断某个类是否是泛型类型或泛型接口的子类型
.NET 中提供了很多判断某个类型或实例是某个类的子类或某个接口的实现类的方法,然而这事情一旦牵扯到泛型就没那么省心了. 本文将提供判断泛型接口实现或泛型类型子类的方法. 本文内容 .NET 中没有自 ...
- JavaScript decodeURI()与decodeURIComponent() 使用与区别
decodeURI()定义和用法:decodeURI()函数可对encodeURI()函数编码过的URI进行解码.语法:decodeURI(URIstring)参数描述:URIstring必需,一个字 ...
- ①Jenkins集成—入门安装使用
一.什么是Jenkins jenkins是一个广泛用于持续构建的可视化web工具,持续构建说得更直白点,就是各种项目的"自动化"编译.打包.分发部署.jenkins可以很好的支持各 ...
- HDU 1969 Pie(二分,注意精度)
Pie Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submiss ...
- 学习笔记之C++入门到精通(名师教学·手把手教会)【职坐标】_腾讯课堂
C++入门到精通(名师教学·手把手教会)[职坐标]_腾讯课堂 https://ke.qq.com/course/101465#term_id=100105503 https://github.com/ ...
- 12步轻松搞定Python装饰器
译者:寒寻 译文:http://www.cnblogs.com/imshome/p/8327438.html 原文:https://dzone.com/articles/understanding-p ...
- 1 预备知识--Hadoop简介
1 预备知识--Hadoop简介 Hadoop是Apache的一个开源的分布式计算平台,以HDFS分布式文件系统和MapReduce分布式计算框架为核心,为用户提供了一套底层透明的分布式基础设施Had ...
- 关于在github上 下载源码 clone 非 master 分支的代码
https://blog.csdn.net/u012302552/article/details/80680497