文档章节

Javascript – How Prototypal Inheritance really ...

子木007
 子木007
发布于 2012/12/14 13:57
字数 841
阅读 45
收藏 0


Everywhere on the web we read that Javascript has prototypal inheritance. However Javascript only provides by default a specific case of prototypal inheritance with the new operator. Therefore, most of the explanations are really confusing to read. This article aims to clarify what is prototypal inheritance and how to really use it on Javascript.

Prototypal Inheritance Definition

When you read about Javascript prototypal inheritance, you often see a definition like this:

When accessing the properties of an object, JavaScript will traverse the prototype chain upwards until it finds a property with the requested name. Javascript Garden

Most Javascript implementations use __proto__ property to represent the next object in the prototype chain. We will see along this article what is the difference between __proto__ and prototype.

Note: __proto__ is non-standard and should not be used in your code. It is used in the article to explain how Javascript inheritance works.

The following code shows how the Javascript engine retrieves a property (for reading).

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

Let's take the usual class example: a 2D Point. A Point has two coordinates x, y and a method print.

Using the definition of the prototypal inheritance written before, we will make an object Point with three properties: x, y and print. In order to create a new point, we just make a new object with __proto__ set to Point.

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

Javascript Weird Prototypal Inheritance

What is confusing is that everyone teaches Javascript prototypal inheritance with this definition but does not give this code. Instead they give something like this:

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.print(); // 10 20

This is completely different from the code given above. Point is now a function, we use a prototype property, the new operator. What the hell!?

How new works

Brendan Eich wanted Javascript to look like traditional Object Oriented programming languages such as Java and C++. In those, we use the new operator to make a new instance of a class. So he wrote a new operator for Javascript.

  • C++ has the notion of constructor, that initializes the instance attributes. Therefore, the new operator must target a function.
  • We need to put the methods of the object somewhere. Since we are working on a prototypal language, let's put it in the prototype property of the function.

The new operator takes a function F and arguments: new F(arguments...). It does three easy steps:

  1. Create the instance of the class. It is an empty object with its __proto__ property set to F.prototype.
  2. Initialize the instance. The function F is called with the arguments passed and this set to be the instance.
  3. Return the instance

Now that we understand what the new operator does, we can implement it in Javascript.

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

And just a small test to see that it works.

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(); // 10 20 console.log(p2 instanceof Point); // true

Real Prototypal Inheritance in Javascript

The Javascript specifications only gives us the new operator to work with. However, Douglas Crockford found a way to exploit the new operator to do real Prototypal Inheritance! He wrote the Object.create function.

Object.create = function (parent) { function F() {} F.prototype = parent; return new F();};

This looks really strange but what it does is really simple. It just creates a new object with its prototype set to whatever you want. It could be written as this if we allow the use of __proto__:

Object.create = function (parent) { return { '__proto__': parent };};

The following code is our Point example with the use of real prototypal inheritance.

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

Conclusion

We have seen what prototypal inheritance is and how Javascript implements only a specific way to do it.

However, the use of real prototypal inheritance (Object.create and __proto__) has some downsides:

  • Not standard: __proto__ is non-standard and even deprecated. Also native Object.create and Douglas Crockford implementation are not exactly equivalent.
  • Not optimized: Object.create (native or custom) has not yet been as heavily optimized as the new construction. It can be up to 10 times slower.

Some further reading:

Bonus

If you can understand with this picture (from the ECMAScript standard) how Prototypal Inheritance works, you get a free cookie!


本文转载自:http://blog.vjeux.com/2011/javascript/how-prototypal-inheritance-really-works.html

共有 人打赏支持
下一篇:
子木007

子木007

粉丝 75
博文 6
码字总数 947
作品 0
徐汇
私信 提问
js中的prototype和构造函数

js中没有类的感念,继承也是通过原型链来实现的对象的继承而不是类的继承 Vjeux写的这篇文章应该能帮助我们更好的理解js中原型的工作方式:http://blog.vjeux.com/2011/javascript/how-proto...

leo-H
2013/04/08
0
0
Angular model objects with JavaScript classes

Angular model objects with JavaScript classes The missing piece in AngularJS Unlike Backbone and Ember, AngularJS does not provide a standardized way to define model objects. Th......

Finley.Hamilton
2014/10/13
0
0
JavaScript继承详解(四)

文章截图 - 更好的排版 在本章中,我们将分析Douglas Crockford关于JavaScript继承的一个实现 - Classical Inheritance in JavaScript。 Crockford是JavaScript开发社区最知名的权威,是JSO...

solu
2010/12/25
0
0
JavaScript 原型精髓,读完这篇就够了

一篇文章让你搞清楚 JavaScript 继承的本质、、、 都是什么。 很多小伙伴表示不明白 JavaScript 的继承,说是原型链,看起来又像类,究竟是原型还是类?各种 、、 内部变量更是傻傻搞不清楚。...

linesh
2018/10/23
0
0
再谈 javascript 面向对象编程

前言:虽有陈皓《Javascript 面向对象编程》珠玉在前,但是我还是忍不住再画蛇添足的补上一篇文章,主要是因为javascript这门语言魅力。另外这篇文章是一篇入门文章,我也是才开始学习Javascr...

aoniao
2012/02/28
4.4K
22

没有更多内容

加载失败,请刷新页面

加载更多

什么时候使用字节流、什么时候使用字符流,二者的区别

在程序中所有的数据都是以流的方式进行传输或保存的,程序需要数据的时候要使用输入流读取数据,而当程序需要将一些数据保存起来的时候,就要使用输出流完成。 InputStream 和OutputStream,...

watermelon11
今天
4
0
Alpakka Kafka,反应式Kafka客户端

Alpakka Kafka 是一个要用于 Java 和 Scala 语言的开源的流感知和反应式集成数据线项目。它建立在 Akka Stream之上,提供了 DSL 来支持反应式和流式编程,内置回压功能。Akka Streams 是 Re...

羊八井
今天
4
0
PHP7源码编译安装详解

$ yum groupinstall "development tools"$ yum install -y gcc gcc-c++ autoconf libjpeg libjpeg-devel libpng libpng-devel freetype \freetype-devel libpng libpng-devel libxml2 ......

问题终结者
今天
5
0
Django学习笔记-从创建虚拟环境到启用服务

1 前置条件 windows系统下,目前已经完成anaconda3或miniconda3的安装,这也意味着已经完成了python3的安装。 2 创建虚拟环境 1、通过Anaconda Prompt,使用conda命令创建虚拟环境(base) e...

davidwbnu
昨天
5
0
python学习04:函数的定义及基本使用

python可以像c++一样,可以直接定义函数。具体格式如下: def(关键字) 函数名(形参01,形参02...): do_something... #如果有返回值,则调用以下语句 return 返回值...

太空堡垒
昨天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部