文档章节

js中的prototype和构造函数

leo-H
 leo-H
发布于 2013/04/08 14:02
字数 887
阅读 622
收藏 6

js中没有类的感念,继承也是通过原型链来实现的对象的继承而不是类的继承

Vjeux写的这篇文章应该能帮助我们更好的理解js中原型的工作方式:http://blog.vjeux.com/2011/javascript/how-prototypal-inheritance-really-works.html

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 toPoint.

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 toF.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 newconstruction. It can be up to 10 times slower.

Some further reading:

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

leo-H
粉丝 24
博文 74
码字总数 28413
作品 0
厦门
私信 提问
漫谈JS中的prototype

1. 引言   继承(inheritance)、封装(encapsulation)和多态(polymorphism)是面向对象机制的主要特性。在JS中没有“class”的概念,自然也无法直接进行JAVA、C++常用到的extends、implement...

solarpig
2018/08/07
0
0
前端基本功(七):javascript中的继承(原型、原型链、继承的实现方式)

1. js的继承机制 javascirpt没有"子类"和"父类"的概念,也没有"类"(class)和"实例"(instance)的区分,全靠一种很奇特的"原型链"(prototype chain)模式,来实现继承。继承意味着复制操作......

大家都叫我四姨
06/18
0
0
关于JavaScript的原型链

关于JavaScript的原型链 JavaScript在ECMA6的class这些关键字出来之前,面向对象编程的方式是基于函数和原型链来实现的。这边涉及到两个东西:contructor和prototype。 本文首先从如何构造一...

csming1995
05/09
0
0
JavaScript继承详解(二)

文章截图 - 更好的排版 这一章我们将会重点介绍JavaScript中几个重要的属性(this、constructor、prototype), 这些属性对于我们理解如何实现JavaScript中的类和继承起着至关重要的作用。 ...

solu
2010/12/22
237
0
关于javascript的原型和原型链,看我就够了(一)

关于js的原型和原型链,有人觉得这是很头疼的一块知识点,其实不然,它很基础,不信,往下看 要了解原型和原型链,我们得先从对象说起 创建对象 创建对象的三种方式: 对象直接量 通过对象直...

陌上寒
2018/11/03
0
0

没有更多内容

加载失败,请刷新页面

加载更多

jquery底层函数-jQuery.ajaxSetup()

jQuery.ajaxSetup( options )返回: 描述: 为以后要用到的Ajax请求设置默认的值 添加的版本: 1.1jQuery.ajaxSetup( options ) options 类型: PlainObject 一个用来配置Ajax请求的"{键:值}"对,......

前端老手
37分钟前
7
0
Qt编写自定义控件56-波浪曲线

一、前言 波浪曲线控件,其实是之前一个水波进度条控件的一个核心,其实就是利用正弦曲线来生成对应的坐标进行绘制,把这个功能单独提取出来,是为了更详细的研究各种正弦余弦等拓展效果,当...

飞扬青云
43分钟前
6
0
深入理解计算机系统cp1:存储单位与编码

摘要: 理解计算机是如何存储数据的。 原文:深入理解计算机系统cp1:存储单位与编码 作者:Chor Fundebug经授权转载,版权归原作者所有。 1. 存储单位 位:即 bit,表示二进制位,要么是 0 ...

Fundebug
46分钟前
6
0
Python查询比特币实时价格

在本文中我们将学习如何使用使用coinmarketcap提供的比特币行情API,编写Python程序来获取像比特币、莱特币或以太币之类的区块链数字货币的实时行情/实时价格。 1、比特币行情API调用代码 我...

汇智网教程
今天
8
0
爬虫平台Crawlab核心原理--自动提取字段算法

⚠注意: 可配置爬虫现在仅在Python版本(v0.2.1-v0.2.4)可用,在最新版本Golang版本(v0.3.0)还暂时不可用,后续会加上,请关注近期更新 背景 实际的大型爬虫开发项目中,爬虫工程师会被要...

tikazyq
今天
6
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部