为什么80%的码农都做不了架构师?>>>   

当查找一个对象的属性时,JS会向上遍历原型链,直到找到给定的属性名称为止,如果没找到就是undefined。

大多数的JS的实现用_proto_属性来表示一个对象的原型链,以下代码展示了JS引擎如何查找属性。

function getProperty(obj, prop) {if (obj.hasOwnProperty(prop))return obj[prop]else if (obj.__proto__ !== null)return getProperty(obj.__proto__, prop)elsereturn undefined}

让我们举一个比较简单的例子,假设有个三维点,坐标x、y、z,同时有print打印方法。

现在我们创建一个对象point,具有x、y、z和print属性,为了能创建一个新的三维坐标点,我们需要创建一个新的对象,使得它的_proto_指向point,继承point。类似C++中的OOP,例如point为基类,创建新的point对象为原先point的子类。

var Point = {x: 0,y: 0,z: 0,print: function () { console.log(this.x, this.y, this.z); }};var p = {x: 10, y: 20, z: 30,__proto__: Point};p.print(); // 10 20 30

但是js工程师一般都不会这样写原型继承,他们如下写出:

function Point(x, y) {this.x = x;this.y = y;this.z = z;}Point.prototype = {print: function () { console.log(this.x, this.y, this.z); }};var p = new Point(10, 20, 30);p.print(); // 10 20 30

这里涉及到了new运算符的工作原理

new后面跟的不是类,而是构造函数 ,用new构造函数生成实例对象,有一个很明显的缺点,就是每个实例无法共享同一个属性和方法。在C++中,如果类中定义了一个static成员,那么所有该类的实例都共享该成员。而JS中每一个实例的对象都有自己属性的副本,这样比较浪费空间,而且无法实现数据的共享。

基于以上new构造函数的缺陷,JS创始人为构造函数添加了prototype属性

prototype属性的引入

JS规定每一个构造函数都有prototype属性,该属性指向另一个对象,另一个对象中所有的属性和方法都会被构造函数的实例引用。

这个属性包含一个对象,所有需要共享的属性和方法放入这个对象中,而不需要共享的属性和方法放入构造函数中。实例对象一旦创建成功,就会自动引用prototype对象中的方法和属性,即实例对象的属性和方法分为两种,一种是本地的,即放入构造函数中的属性和方法,一种是引用的,即放入prototype对象。例如以下代码:

function DOG(name){this.name = name;}DOG.prototype = { species : '犬科' };var dogA = new DOG('大毛');var dogB = new DOG('二毛');alert(dogA.species); // 犬科alert(dogB.species); // 犬科

在这个例子中,species属性放入prototype对象中,那么实例dogA和dogB共用species属性。只要其中一个实例的species发生改变,则会影响所有实例的species

Prototype模式的验证方法

isPrototypeOf

这个方法用来判断prototype对象和某个实例之间的关系,例如

alert(DOG.prototype.isPrototypeOf(dogA)); //true
hasOwnProperty

每一个实例对象都有一个该方法,用来判断该实例中的某个属性是来自本地属性,还是继承自原型对象属性。例如

alert(dogA.hasOwnProperty(name))//true
in运算符

in运算符可以判断某个属性是否属于实例对象,不管是本地属性还是继承自原型对象属性。如

alert("name" in dogA); //true
alert("species" in dogA); //true

in运算符还可以遍历某个对象的所有属性,如

for (var prop in dogA) {
alert(prop);
}

测试

有一道阿里的在线前端笔试题,题目如下:

现在有如下的代码:

var foo = 1;
function main(){console.log(foo);var foo = 2;console.log(this.foo)this.foo = 3;}

1.请给出以下两种方式调用函数时,输出的结果,并说明原因

var m1 = main();
var m2 = new main();

2.如果需要var m1= main()产生的结果与前面m2产生结果一样,应该如何改造main函数

第一题解答:首先根据JS的变量提升规则,可以知道,全局的foo被main函数屏蔽了,main函数在内部定义了一个foo同名的变量,该变量在第一个console之前只定义而未赋值,故为undefined(undefined有两种情况会出现,已定义未赋值,未定义)。而在第二个console的时候,this指向的是window,故输出为1

转载于:https://my.oschina.net/u/866703/blog/214544

JS原型继承工作原理相关推荐

  1. JS原型继承和类式继承

    类式继承(构造函数) JS中其实是没有类的概念的,所谓的类也是模拟出来的.特别是当我们是用new 关键字的时候,就使得"类"的概念就越像其他语言中的类了.类式继承是在函数对象内调用 ...

  2. java线程工作原型_深度解析Java内存的原型及工作原理

    本文主要通过分析Java内存分配的栈.堆以以及常量池详细的讲解了其的工作原理. 一.java虚拟机内存原型 寄存器:我们在程序中无法控制栈:存放基本类型的数据和对象的引用,但对象本身不存放在栈中,而是 ...

  3. js原型继承——prototype的使用

    文章目录 prototype的定义 原型链继承 修改prototype 继承的子类能否覆盖父类属性 总结 一些笔试题 第一题 第二题 小彩蛋 结语 参考文章 prototype的定义 javascri ...

  4. JS原型继承,盗用构造函数,组合继承,原型式继承

    继承 ECMA-262 把原型链定义为 ECMAScript 的主要继承方式.其基本思想就是通过原型继承多个引用类型的属性和方法. 原型链 重温一下构造函数.原型和实例的关系:每个构造函数都有一个原型 ...

  5. 解释下原型继承的原理。

    prototype与[[prototype]] 在有面象对象基础的前提下,来看一段代码: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 //Animal构造函数 fun ...

  6. js原型和原型链_初识JS原型/原型链/原型继承

    本文思路: 原型->原型链->原型继承->基于原型的继承/ES6中的继承->__proto__与prototype 首先我们知道JS中有对象,比如: var 但是在我们没有对这 ...

  7. 翻译:原型继承是如何工作的

    原文链接 前言:本人表述能力不太好,如果有不清晰的地方请一定回复,我会改. 每个人都知道js有原型继承.但js只默认提供了 new 运算符实现特定的原型继承.所以,大多数的说明都很难读懂.这篇文章目的 ...

  8. python继承方式是基于原型吗_[译] 为什么原型继承很重要

    五天之前我写了一个关于ES6标准中Class的文章.在里面我介绍了如何用现有的Javascript来模拟类并且介绍了ES6中类的用法,其实它只是一个语法糖.感谢Om Shakar以及Javascrip ...

  9. JS高级进阶总结day01---面向对象编程介绍,new的工作原理以及构造函数,原型对象,实力函数三者之间的关系

    02-面向对象编程 1.1-面向对象编程介绍 本小节知识点 1.理解什么是面向对象编程 面向对象不是一门技术,而是一种解决问题的思维方式 面向对象的本质是对面向过程的一种封装 2.理解什么是对象 对象 ...

最新文章

  1. SQL 简单,复杂查询,基本函数查询
  2. android pcm频谱_Android音频可视化
  3. 基于SpringJDBC 实现关键功能-QueryRuleSqlBulider
  4. 看苏宁易购的运营保障体系如何hold住818大促
  5. ubantu系统下修改计算机名字
  6. POJ2676Sudoku
  7. 20190720学习小结
  8. Auto.js 如何WIFI连接VS Code插件
  9. springboot的三种启动方式
  10. 【系统分析师之路】第五章 复盘软件工程(软件过程改进)
  11. android 坐标度分秒转换工具,经纬度格式转换定位工具
  12. Android 动画 - TranslateAnimation位移动画
  13. PTA 02-线性结构3 Reversing Linked List 题目解析
  14. 游戏美术次世代制作流程图文详解
  15. 客制化键盘编程_装机单推荐 篇二:垃圾佬的第一个客制化键盘---gk64升级版
  16. 景区自定义手绘地图叠加
  17. MFC-SaoChat(模仿QQ)聊天软件
  18. python语句中print(0xa+0xb)的输出结果是_【单选题】Python语句print(0xA+0xB)的输出结果是( )...
  19. Docker精华问答 | Docker commit如何用?
  20. 知识丨软件定义汽车下的整车开发

热门文章

  1. Spring Boot项目能之前能正常跑,安装禅道后突然就不行了报错Unknown database “数据库名“
  2. java 反射解读理解
  3. java 打印gc_java – 以编程方式打印启用GC日志记录时通常在JVM出口上打印的堆使用情况...
  4. python支持复数以及相关的运算吗_Python复数属性和方法运算操作示例
  5. element元素 取属性_JS-DOM Element方法和属性
  6. node 获取表单数据 为空_寻offer之JS数据结构与算法 -- 栈
  7. 怎么看so文件是哪个aar引进来的_突破微信限制,超大文件可以随便发
  8. 关于easyui combobox下拉框实现多选框的实现
  9. 无名接口.php,李无名
  10. 获取所有task_Asp.Net Core 轻松学-多线程之Task快速上手