原文链接

前言:本人表述能力不太好,如果有不清晰的地方请一定回复,我会改。

每个人都知道js有原型继承。但js只默认提供了 new 运算符实现特定的原型继承。所以,大多数的说明都很难读懂。这篇文章目的就是说清楚什么是原型继承,和怎么在js中使用原型继承。

原型继承的定义

当你读到关于js的原型继承,经常能看到如下定义:

当访问对象的属性时,JavaScript将向上遍历原型链,直到找到具有对应的属性- -- Javascript Garden

大多数js的实现使用了 __proto__ 属性来表示原型链中的下一个对象。在本文中将看到 __proto__ 与 prototype 的区别。

:ledger: __proto__ 非标准的,代码中不应该使用。他在这篇文章中用来解释js原型是怎么工作的。

下面的代码展示了js引擎怎么检索属性

function getProperty(obj, prop) {if (obj.hasOwnProperty(prop))return obj[prop]else if (obj.__proto__!=null)return getProperty(obj.__proto__, prop)else return undefinded
}复制代码

我们用一个经典例子:一个二维点。一个点有两个坐标 x , y 和一个方法 print

用前面写到的原型链的定义,我们将写一个对象 Point ,他有三个属性 x,y, print 。为了创建一个新的二维点,我们写了一个对象,并设置了 __proto__

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

诡异的js原型继承

知道什么最让人迷惑吗?每个这样定义原型继承的人不写这样的代码,他们代码是这样的:

function Point(x,y){this.x = x;this.y = y;
}
Point.prototype = {print: function () { console.log(this.x, this.y); }
}
var p = new Point(10, 20);
p.point(); // 10 20复制代码

这个就和上面的那段代码完全不一样了。 Point 现在是个 function ,有个 prototype 属性,还有 new 运算符。都什么鬼?

new 是怎么工作的?

Brendan Eich   希望 js 是个传统的面向对象的编程语言,就像 Java 和 C++ 一样。在这些语言中,使用new运算符创建类的实例。所以他给 js 写了个 new 运算符。

  • C++ 有构造函数的概念,初始化实例属性。所以, new 操作目标必须是函数。
  • 我们需要要把对象的方法放在某个地方。既然js是个原型语言( prototype language ),那就放在方法的 prototype 属性上吧。

new 运算符有方法F和参数: new F(arguments) 。做了单个简单的步骤:

  1. 创建类的实例。一个空对象将 __proto__ 属性设置为 F.prototype
  2. 实例化。 F 及其参数集被调用,并把 this 设置上去
  3. 返回该实例

现在我们理解了 new 做了什么,可以用 js 实现它

function New(f){
/*1*/    var n = {__proto__:f.prototype};return function(){
/*2*/       f.apply(n, arguments);
/*3*/       return n;};}复制代码

测试下

function Point(x,y) {this.x= x;this.y=y
}
Point.prototype = {print: function(){console.log(this.x,this.y)}
};
var p1 = new Point(10, 20);
p1.print();// 10 20
console.log(p1 instanceof Point);// true
var p2 = New(Point)(10,20);
p2.print();
console.log(p2 instanceof Point);// true复制代码

js里真实的原型继承

JavaScript规范 只提供了 new 运算符。但Douglas Crockford找到了利用 new 运算符实现真正的原型继承的方法。我们现在写 Object.create 方法。

Object.create = function(parent) {function F() {};F.prototype = parent;return new F();
};复制代码

这看上去很奇怪,但是它做的事情却很简单。它只是创建了一个新对象,并把 prototype 设置为任何你想设置的。如果可以使用 __proto__ ,他就可以写成这样

Object.create = function(parent) {    return  {__proto__: parent};
};复制代码

下面的代码是用真正的原型继承实现的 Point

var Point = {x: 0,y: 0,print: function () { console.log(this.x, this.y); }
};var p = Object.create(Point);
p.x = 10;
p.y = 20;
p.print(); // 10 20复制代码

总结

我们知道了原型继承是什么,以及 js 是怎么实现它的。

但是,原型继承的使用( Object.create and __proto__ )有几个缺陷:

  • 不标准: __proto__ 是非标准的甚至反对这样做。而 Object.create 和Douglas Crockford的实现不完全等同。
  • 没优化: Object.create 还没有像 new 构造一样优化。要 慢了10倍

一些深入阅读:

翻译:原型继承是如何工作的相关推荐

  1. JS原型继承工作原理

    为什么80%的码农都做不了架构师?>>>    当查找一个对象的属性时,JS会向上遍历原型链,直到找到给定的属性名称为止,如果没找到就是undefined. 大多数的JS的实现用_p ...

  2. 原型和原型链原型继承_原型还是不原型:这就是问题所在。

    原型和原型链原型继承 by Rishal Hurbans 由Rishal Hurbans 原型还是不原型:这就是问题所在. (To prototype or not to prototype: tha ...

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

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

  4. 原型和原型链原型继承_我如何看待Flash的教训,拥有原型的未来

    原型和原型链原型继承 Prototyping is critical part of UX process. Obviously, prototyping tools play significant ...

  5. 动图学 JavaScript 之:原型继承

    前言 你是否曾思考为什么我们能使用 JS 中的一些内置属性和方法,比如 .length,.split(),.join()?我们并没有显式地声明它们,那么究竟它们从哪里来的呢?可不要说什么"那 ...

  6. 原型和原型链原型继承_原型制作的最甜蜜的一面

    原型和原型链原型继承 交战的原因 (Casus belli) Let's start from the context: I was working as a UX/UI designer for a ...

  7. 再论JavaScript原型继承和对象继承

    JavaScript的原型继承是老生常谈.由于原型即prototype本身也是对象,所以"原型"继承可认为是一种特殊的"对象式"继承."对象式&quo ...

  8. 理解JavaScript中的原型继承(2)

    两年前在我学习JavaScript的时候我就写过两篇关于原型继承的博客: 理解JavaScript中原型继承 JavaScript中的原型继承 这两篇博客讲的都是原型的使用,其中一篇还有我学习时的错误 ...

  9. html 原型图片,可视化的JavaScript:原型继承(动图演示)

    你是否曾思考为什么我们能使用 JS 中的一些内置属性和方法,比如 .length,.split(),.join()?我们并没有显式地声明它们,那么究竟它们从哪里来的呢? 可不要说什么"那是 ...

最新文章

  1. substring java_Java String.substring()用法
  2. python代码优化_Python 代码优化技巧(一)
  3. python之禅 中文_《Python之禅》中对于Python编程过程中的一些建议
  4. mongodb 的windows 下安装
  5. java--java语言基础(4)--黑马程序员
  6. LeetCode 692. 前K个高频单词(优先队列)
  7. 钉钉打卡如何破译人脸识别_疫情常态下,如何选择合适的考勤管理系统和考勤打卡工具?...
  8. java test20006_java 数组 (数组个数小于2000)
  9. android学习笔记---55_frame动画的实现,Java技术qq交流群:JavaDream:251572072
  10. ubuntu16 安装opencv
  11. JavaScript文档对象模型概述(1)
  12. Appfuse:扩展自己的GenericManager
  13. 使用DroidCam过程中所遇到的问题及处理方法
  14. win10,win11内存占用过高
  15. 成都双流计算机大专学校,成都双流有哪些好的职业学校?
  16. 中国石油大学(北京)-《 公共社交礼仪 》-​​​​​​​第二阶段在线作业
  17. 世界曾经有这样一个中国
  18. html特效代码 枫叶,经典FLASH特效代码
  19. 1071: 数塔 (动态规划)
  20. 微信小游戏和微信小程序的区别与共同

热门文章

  1. solidworks两条线重合了如何选其中一条
  2. vue项目目录结构解释
  3. Java集合包含面试题
  4. L1-070 吃火锅(C语言)
  5. 弘辽科技:2021年淘宝618优惠券玩法招商
  6. [中国近代史] 第六章测验
  7. git提交代码更换提交人
  8. 笔记本电脑CPU正常温度是多少?怎样控制与防范?
  9. 动手学深度学习在线课程-跟着李沐学AI
  10. 短视频app源码:yoo视频更名火锅视频,开启长带短新模式