JavaScript中的prototype和__proto__细致解析
最近在学js,体会了一点点它的灵活性。对于初学者的我,总是被它的灵活感到晕头转向,最近发现了一点东西想与大家分享。
JavaScript中的prototype和_proto_:
我们先了解一点js中的基础知识,首先我们先看一段js代码:
var object = new Object;
console.log("object:", object);
object.member1 = "abcd"; var obj = {};
obj.member1 = 10;
console.log("obj:", obj);
console.log(window);
输出结果:

对于上面输出结果,我总结了几点:
1.js的对象事实上是关联数组;
2.js对象中的成员的增加,可以通过直接赋值即可。
3.“值”是由键值对组成。
我们再来看一段代码(真是不得不说代码是最值得信赖的。)
var Klass = function() {};
var Fun = new Function();
Klass.mem = 10;
Fun.mem = true;
var klass = new Klass; //klass是Klass的一个对象。
console.log(klass instanceof Klass);
console.log(window);
输出结果:

首先,我们不得不承认,js中的一个function,拥有三个身份:对象、函数、类。
上述代码(var klass = new Klass;)的执行过程是:
1.申请一个Klass的对象klass实例空间;
2.将空间首地址赋值给对象klass;
3.执行Klass的构造方法;这个构造方法就是函数本身;
4.这个构造方法在执行时,是有前缀的(有对象的),而这个对象就是Klass;那么,构造方法中的this就是klass。
(第四点用Java语言讲是最合适不过了,Java中的类都有构造方法,构造方法中的this相当于new出来的对象实例,不管有多少个实例,他们都是this。)
下面进行主题:继续看代码:
function Fun() {
this.num = 22;
};
var fun = new Fun;
var func = new Fun;
console.log(window);
console.log("Fun:", Fun);
console.log("fun:", fun);
console.log("func:", func);
var Klass = function() {}; // Klass是类
var Fun = new Function(); //Fun是类
console.log("Klass:", Klass);
console.log("Fun:", Fun);
结果:

1.从结果可以看到:类Fun、 Klass、Fun显示有prototype成员,而对象klass和func没有prototype成员。
所以只有类(函数)才有prototype成员,这个成员被称为“原型对象”,它指向一个空间,称为原型空间。 2.还有结结果:fun和func有num成员,但是类没有。这就证实了我们刚刚的说法: (var fun = new Fun;var func = new Fun;的执行过程)再强调一遍:1.申请一个对象实例空间;
2.将空间首地址赋值给对象fun和func;
3.执行Klass的构造方法;这个构造方法就是函数本身;
4、这个构造方法在执行时,是有前缀的(有对象的),而这个对象就是fun和func;那么,构造方法中的this就是fun和func (第四点用Java语言讲是最合适不过了,Java中的类都有构造方法,构造方法中的this相当于new出来的对象实例,不管有多少个实例,他们都是this。)console.log("Fun.prototype:", Fun.prototype);

从以上代码和结果,我们可以看到:类的原型本身也是对象(object),那么,既然是对象,就可以增加成员:
Fun.prototype.member = "这是prototype的一个成员";
console.log("fun.prototype:", fun.prototype);

上上面的代码和结果,我们可以更加坚定的得出结论是:
所以只有类(函数)才有prototype成员,对象不存在prototype成员。这也是检验对象是否是函数的一种判断方法。
console.log("fun.member:", fun.member);
console.log("func.member:", func.member);
console.log("fun.__proto__:",fun.__proto__);
console.log("func.__proto__:", func.__proto__);

从上面的代码和结果我们可以看到:
我们并没有给fun和func增加过__proto__成员,输出结果却有,而我们仔细一点打开Fun类的成员prototype,
他们三个的输出结果居然一模一样,所以,我给出一个结论:对象__proto__这个隐藏的成员,这个隐藏成员指向prototype所指向的原型空间。
func.__proto__.member = 100;
console.log("Fun.prototype.member:", Fun.prototype.member);
console.log("Fun.member:", Fun.member);

给对象func的__proto__成员增加一个成员member,即__proto__指向prototype原型空间,所以有了member成员。
但是我们从结果可以看出:类不能直接访问原型对象的member成员,只能通过prototype访问其原型对象的member成员。
我再总结一点关于js中的左值和右值的不同处理过程:
右值:
1、右值被看成空间,严格地说,右值也被看成“键”;
2、对于形如“xxx.成员”的右值,首先在xxx的键值对中查找,若存在,则,取出其值,并结束查找;
若不存在,则,会自动沿着__proto__所指向的原型空间进行查找;
3、prototype本身也是对象,也应该存在__proto__隐含成员;
4、第2步的查找,会沿着这个隐含原型链,查找所有“祖先”原型空间中的“右值”;
5、当遍历了所有原型空间,依然找不到这个“键”(右值),则,其值为undefined。
左值:
1、左值被看成空间,严格地说,左值也被看成“键”;
2、对于形如“xxx.成员”的左值,首先在xxx的键值对中查找,若存在,则,用=右侧的表达式的值覆盖其值;
3、若不存在,则,增加一个成员,再完成赋值。
(例如:若func.__proto__.member = 18;在func.__proto__的键值对中查找,没有找到member成员,则增加了一个func.__proto__成员,并赋值为18。)
console.log("Function:", Function);
console.log("Object.__proto__:", Object.__proto__);
console.log("Object.__proto__ === Function.prototype:", Object.__proto__ === Function.prototype);

Function的__proto__成员指向Function的原型空间。
console.log("Function.prototype.__proto__:",Function.prototype.__proto__);
console.log("Object.prototype:",Object.prototype);

从上面的代码可以看出:
Function的原型空间prototype的__proto__成员指向Object的原型空间,显示的是相同的结果。
最后稍微的总结一下:
1、只有类(函数)才有prototype成员,这个成员被称为“原型对象”,它指向一个空间,称为原型空间;
2、类的原型本身也是对象,可以增加成员;
3、对象不存在prototype成员,这是检验对象是否是函数的一种判断方法;
4、对象存在__proto__这个隐藏的成员,这个成员指向prototype所指向的原型空间;
5、通过类(函数)不能直接访问其原型的成员,必须通过prototype访问原型成员。
画出手工图:

补充一点:
1、在类构造方法中,用this定义的成员,可以等效为Java的public成员;
2、在类.prototype中定义的成员,可以等效为Java的public staitc成员,即,该类的所有对象共享同一副本;
3、对原型成员的标准访问方法是:类.prototype.成员。
4、以上若有错误请指正!
JavaScript中的prototype和__proto__细致解析的更多相关文章
- Javascript中的prototype和__proto__的联系区别
转载至http://www.cnblogs.com/sinstone/p/5136871.html 一.联系 prototype和__proto__都指向原型对象,任意一个函数(包括构造函数)都有 ...
- javascript中的prototype和__proto__的理解
在工作中有时候会看到prototype和__proto__这两个属性,对这两个属性我一直比较蒙圈,但是我通过查阅相关资料,决定做一下总结加深自己的理解,写得不对的地方还请各位大神指出. 跟__prot ...
- 彻底理解JavaScript中的prototype、__proto__
虽然在JavaScript里一切皆对象,但为了理解原型链系统,我们需要将JavaScript的对象分为对象和函数两大类.在此基础上,JavaScript的原型链逻辑遵从以下通用规则: 对象有__pro ...
- JavaScript 中 的prototype和__proto__
1.prototype是函数的一个属性(每个函数都有一个prototype属性),这个属性是一个指针,指向一个对象.它是显示修改对象的原型的属性. 2.__proto__是一个对象拥有的内置属性(请注 ...
- Javascript中Function,Object,Prototypes,__proto__等概念详解
http://anykoro.sinaapp.com/2012/01/31/javascript%E4%B8%ADfunctionobjectprototypes__proto__%E7%AD%89% ...
- JavaScript原型链:prototype与__proto__
title: 'JavaScript原型链:prototype与__proto__' toc: false date: 2018-09-04 11:16:54 主要看了这一篇,讲解的很清晰,最主要的一 ...
- 帮你彻底搞懂JS中的prototype、__proto__与constructor(图解)
作为一名前端工程师,必须搞懂JS中的prototype.__proto__与constructor属性,相信很多初学者对这些属性存在许多困惑,容易把它们混淆,本文旨在帮助大家理清它们之间的关系并彻底搞 ...
- 原型链继承中的prototype、__proto__和constructor的关系
前不久写了有关原型链中prototype.__proto__和constructor的关系的理解,这篇文章说说在原型链继承中的prototype.__proto__和constructor的关系. 通 ...
- JavaScript中Object.prototype.toString方法的原理
在JavaScript中,想要判断某个对象值属于哪种内置类型,最靠谱的做法就是通过Object.prototype.toString方法. ? 1 2 var arr = []; console.lo ...
随机推荐
- Vue小案例 之 商品管理------学习过滤器 使用过滤器处理日期的格式
代码学习过滤器 过滤器介绍:过滤模型数据,在数据显示前做预处理操作: 内置过滤器:在1.x中,Vue提供了内置过滤器,但是在2.x中已经完全废除: 解决办法: (1)使用第三方库来替代1.x中的内置过 ...
- Android之单元测试及数据库操作
一.安卓下的单元测试1.创建一个单元类,继承超类AndroidTestCase2.在AndroidManifest.xml配置清单中配置以下两点首先在manifest节点下添加节点instrument ...
- 20145208 蔡野 《网络对抗》Exp7 网络欺诈技术防范
20145208 蔡野 <网络对抗>Exp7 网络欺诈技术防范 本实践的目标理解常用网络欺诈背后的原理,以提高防范意识,并提出具体防范方法.具体有(1)简单应用SET工具建立冒名网站(2) ...
- 20145208 蔡野 《网络对抗》Exp6 信息搜集与漏洞扫描
20145208 蔡野 <网络对抗>Exp6 信息搜集与漏洞扫描 本实践的目标是掌握信息搜集的最基础技能.具体有(1)各种搜索技巧的应用(2)DNS IP注册信息的查询 (3)基本的扫描技 ...
- 动态规划之132 Palindrome Partitioning II
题目链接:https://leetcode-cn.com/problems/palindrome-partitioning-ii/description/ 参考链接:https://blog.csdn ...
- uniGUI试用笔记(九)
uniGUI执行程序部署有3种形式 1.ISAPI模式 部署在IIS或Apache,程序编译为Dll形式,没有试,准备后续专门测试一下. 2.标准执行文件模式 将软件编译成一个独立的Exe文件,包括了 ...
- Python3 tkinter基础 Frame bind 鼠标移动事件 实时显示鼠标的位置
Python : 3.7.0 OS : Ubuntu 18.04.1 LTS IDE : PyCharm 2018.2.4 Conda ...
- Django框架 (一) 虚拟环境配置及简单使用
虚拟环境 什么是虚拟环境 对真实的python解释器的一个拷贝版本 是事实有效的,可以独立存在运行解释python代码 可以在计算机上拷贝多个虚拟环境 为什么要使用虚拟环境 保证真实环境的纯净性 框架 ...
- 5. 多重背包问题 II 【用二进制优化】
多重背包问题 II 描述 有 NN 种物品和一个容量是 VV 的背包. 第 ii 种物品最多有 sisi 件,每件体积是 vivi,价值是 wiwi. 求解将哪些物品装入背包,可使物品体积总和不超过背 ...
- Python hasattr() 函数 // python中hasattr()、getattr()、setattr()函数的使用
http://www.runoob.com/python/python-func-hasattr.html https://www.cnblogs.com/zanjiahaoge666/p/74752 ...