非常好的文章: http://javascriptissexy.com/javascript-prototype-in-plain-detailed-language/

jan. 25 2013 147

Prototype is a fundamental concept that every JavaScript developer must understand, and this article aims to explain JavaScript’s prototype in plain, detailed language. If you don’t understand JavaScript’s prototype after reading this blog post, please ask questions in the comments below. I will personally answer all questions.

To understand prototype in JavaScript you must understand objects in JavaScript. If you aren’t already familiar with objects, you should read my post JavaScript Objects in Detail. Also, know that a property is simply a variable defined on a function.

  • Receive Updates

There are two interrelated concepts with prototype in JavaScript:

  1. First, every JavaScript function has a prototype property (this property is empty by default), and you attach properties and methods on this prototype property when you want to implement inheritance. This prototype property is not enumerable; that is, it isn’t accessible in a for/in loop. But Firefox and most versions of Safari and Chrome have a __proto__ “pseudo” property (an alternative syntax) that allows you to access an object’s prototype property. You will likely never use this __proto__ pseudo property, but you should know that it exists and it is simply a way to access an object’s prototype property in some browsers.

    The prototype property is used primarily for inheritance; you add methods and properties on a function’s prototype property to make those methods and properties available to instances of that function.

    Consider this simple example of inheritance with the prototype property (more on inheritance later):

      function PrintStuff (myDocuments) {
      ​this.documents = myDocuments;
      }
     
      ​// We add the print () method to PrintStuff prototype property so that other instances (objects) can inherit it:​
      PrintStuff.prototype.print = function () {
      console.log(this.documents);
      }
     
      ​// Create a new object with the PrintStuff () constructor, thus allowing this new object to inherit PrintStuff's properties and methods.​
      ​var newObj = new PrintStuff ("I am a new Object and I can print.");
     
      ​// newObj inherited all the properties and methods, including the print method, from the PrintStuff function. Now newObj can call print directly, even though we never created a print () method on it.​
      newObj.print (); //I am a new Object and I can print.
  2. The second concept with prototype in JavaScript is the prototype attribute. Think of the prototype attribute as a characteristic of the object; this characteristic tells us the object’s “parent”. In simple terms: An object’s prototype attribute points to the object’s “parent”—the object it inherited its properties from. The prototype attribute is normally referred to as the prototype object, and it is set automatically when you create a new object.To expound on this: Every object inherits properties from some other object, and it is this other object that is the object’s prototype attribute or “parent.” (You can think of the prototype attribute as the lineage or the parent). In the example code above, newObj‘s prototype is PrintStuff.prototype.

    Note: All objects have attributes just like object properties have attributes. And the object attributes are prototype, class, and extensible attributes. It is this prototype attribute that we are discussing in this second example.

    Also note that the __proto__ “pseudo” property contains an object’s prototype object (the parent object it inherited its methods and properties from).

Constructor
Before we continue, let’s briefly examine the constructor. A constructor is a function used for initializing new objects, and you use the new keyword to call the constructor.
For example:

  function Account () {
  }
  ​// This is the use of the Account constructor to create the userAccount object.​
  ​var userAccount = new Account ();

Moreover, all objects that inherit from another object also inherit a constructor property. And this constructor property is simply a property (like any variable) that holds or points to the constructor of the object.

  //The constructor in this example is Object () ​
  ​var myObj = new Object ();
  ​// And if you later want to find the myObj constructor:​
  console.log(myObj.constructor); // Object()​
 
  ​// Another example: Account () is the constructor​
  ​var userAccount = new Account ();
  ​// Find the userAccount object's constructor​
  console.log(userAccount.constructor); // Account()

Prototype Attribute of Objects Created with new Object () or Object Literal
All objects created with object literals and with the Object constructor inherits from Object.prototype. Therefore, Object.prototype is the prototype attribute (or the prototype object) of all objects created with new Object () or with {}. Object.prototype itself does not inherit any methods or properties from any other object.

  // The userAccount object inherits from Object and as such its prototype attribute is Object.prototype.​
  ​var userAccount = new Object ();
 
  ​// This demonstrates the use of an object literal to create the userAccount object; the userAccount object inherits from Object; therefore, its prototype attribute is Object.prototype just as the userAccount object does above.​
  ​var userAccount = {name: “Mike”}

Prototype Attribute of Objects Created With a Constructor Function
Objects created with the new keyword and any constructor other than the Object () constructor, get their prototype from the constructor function.

For Example:

  function Account () {
 
  }
  ​var userAccount = new Account () // userAccount initialized with the Account () constructor and as such its prototype attribute (or prototype object) is Account.prototype.

Similarly, any array such as var myArray = new Array (), gets its prototype from Array.prototype and it inherits Array.prototype’s properties.

So, there are two general ways an object’s prototype attribute is set when an object is created:

  1. If an object is created with an object literal (var newObj = {}), it inherits properties from Object.prototype and we say its prototype object (or prototype attribute) is Object.prototype.
  2. If an object is created from a constructor function such as new Object (), new Fruit () or new Array () or new Anything (), it inherits from that constructor (Object (), Fruit (), Array (), or Anything ()). For example, with a function such as Fruit (), each time we create a new instance of Fruit (var aFruit = new Fruit ()), the new instance’s prototype is assigned the prototype from the Fruit constructor, which is Fruit.prototype.Any object that was created with new Array () will have Array.prototype as its prototype. An object created with new Fruit () will have Fruit.prototype as its prototype. And any object created with the Object constructor (Obj (), such as var anObj = new Object() ) inherits from Object.prototype.

It is important to know that in ECMAScript 5, you can create objects with an Object.create() method that allows you to set the new object’s prototype object. We will cover ECMAScript 5 in a later post.

Why is Prototype Important and When is it Used?
These are two important ways the prototype is used in JavaScript, as we noted above:

  1. Prototype Property: Prototype-based Inheritance
    Prototype is important in JavaScript because JavaScript does not have classical inheritance based on Classes (as most object oriented languages do), and therefore all inheritance in JavaScript is made possible through the prototype property. JavaScript has a prototype-based inheritance mechanism.Inheritance is a programming paradigm where objects (or Classes in some languages) can inherit properties and methods from other objects (or Classes). In JavaScript, you implement inheritance with the prototype property. For example, you can create a Fruit function (an object, since all functions in JavaScript are objects) and add properties and methods on the Fruit prototype property, and all instances of the Fruit function will inherit all the Fruit’s properties and methods.

    Demonstration of Inheritance in JavaScript:

      function Plant () {
      ​this.country = "Mexico";
      ​this.isOrganic = true;
      }
     
      ​// Add the showNameAndColor method to the Plant prototype property​
      Plant.prototype.showNameAndColor = function () {
      console.log("I am a " + this.name + " and my color is " + this.color);
      }
     
      ​// Add the amIOrganic method to the Plant prototype property​
      Plant.prototype.amIOrganic = function () {
      ​if (this.isOrganic)
      console.log("I am organic, Baby!");
      }
     
      ​function Fruit (fruitName, fruitColor) {
      ​this.name = fruitName;
      ​this.color = fruitColor;
      }
     
      ​// Set the Fruit's prototype to Plant's constructor, thus inheriting all of Plant.prototype methods and properties.​
      Fruit.prototype = new Plant ();
     
      ​// Creates a new object, aBanana, with the Fruit constructor​
      ​var aBanana = new Fruit ("Banana", "Yellow");
     
      ​// Here, aBanana uses the name property from the aBanana object prototype, which is Fruit.prototype:​
      console.log(aBanana.name); // Banana​
     
      ​// Uses the showNameAndColor method from the Fruit object prototype, which is Plant.prototype. The aBanana object inherits all the properties and methods from both the Plant and Fruit functions.​
      console.log(aBanana.showNameAndColor()); // I am a Banana and my color is yellow.

    Note that the showNameAndColor method was inherited by the aBanana object even though it was defined all the way up the prototype chain on the Plant.prototype object.

    Indeed, any object that uses the Fruit () constructor will inherit all the Fruit.prototype properties and methods and all the properties and methods from the Fruit’s prototype, which is Plant.prototype. This is the principal manner in which inheritance is implemented in JavaScript and the integral role the prototype chain has in the process.

    For more in-depth coverage on Objective Oriented Programming in JavaScript, get Nicholas Zakas’s Principles of Object-Oriented Programming in JavaScript (it is only $14.99).

  2. Prototype Attribute: Accessing Properties on Objects
    Prototype is also important for accessing properties and methods of objects. The prototype attribute (or prototype object) of any object is the “parent” object where the inherited properties were originally defined.This is loosely analogous to the way you might inherit your surname from your father—he is your “prototype parent.” If we wanted to find out where your surname came from, we would first check to see if you created it yourself; if not, the search will move to your prototype parent to see if you inherited it from him. If it was not created by him, the search continues to his father (your father’s prototype parent).

    Similarly, if you want to access a property of an object, the search for the property begins directly on the object. If the JS runtime can’t find the property there, it then looks for the property on the object’s prototype—the object it inherited its properties from.
    If the property is not found on the object’s prototype, the search for the property then moves to prototype of the object’s prototype (the father of the object’s father—the grandfather). And this continues until there is no more prototype (no more great-grand father; no more lineage to follow). This in essence is the prototype chain: the chain from an object’s prototype to its prototype’s prototype and onwards. And JavaScript uses this prototype chain to look for properties and methods of an object.
    If the property does not exist on any of the object’s prototype in its prototype chain, then the property does not exist and undefined is returned.

    This prototype chain mechanism is essentially the same concept we have discussed above with the prototype-based inheritance, except we are now focusing specifically on how JavaScript accesses object properties and methods via the prototype object.

    This example demonstrates the prototype chain of an object’s prototype object:

      var myFriends = {name: "Pete"};
     
      ​// To find the name property below, the search will begin directly on the myFriends object and will immediately find the name property because we defined the property name on the myFriend object. This could be thought of as a prototype chain with one link.​
      console.log(myFriends.name);
     
      ​// In this example, the search for the toString () method will also begin on the myFriends’ object, but because we never created a toString method on the myFriends object, the compiler will then search for it on the myFriends prototype (the object which it inherited its properties from).​
     
      ​// And since all objects created with the object literal inherits from Object.prototype, the toString method will be found on Object.prototype—see important note below for all properties inherited from Object.prototype. ​
     
      myFriends.toString ();
    Object.prototype Properties Inherited by all Objects
    All objects in JavaScript inherit properties and methods from Object.prototype. These inherited properties and methods are constructor, hasOwnProperty (), isPrototypeOf (), propertyIsEnumerable (), toLocaleString (), toString (), and valueOf (). ECMAScript 5 also adds 4 accessor methods to Object.prototype.

    Here is another example of the prototype chain:

      function People () {
      ​this.superstar = "Michael Jackson";
      }
      ​// Define "athlete" property on the People prototype so that "athlete" is accessible by all objects that use the People () constructor.​
      People.prototype.athlete = "Tiger Woods";
     
      ​var famousPerson = new People ();
      famousPerson.superstar = "Steve Jobs";
     
      ​// The search for superstar will first look for the superstar property on the famousPerson object, and since we defined it there, that is the property that will be used. Because we have overwritten the famousPerson’s superstar property with one directly on the famousPerson object, the search will NOT proceed up the prototype chain. ​
      console.log (famousPerson.superstar); // Steve Jobs​
     
      ​// Note that in ECMAScript 5 you can set a property to read only, and in that case you cannot overwrite it as we just did.​
     
      ​// This will show the property from the famousPerson prototype (People.prototype), since the athlete property was not defined on the famousPerson object itself.​
      console.log (famousPerson.athlete); // Tiger Woods​
     
      ​// In this example, the search proceeds up the prototype chain and find the toString method on Object.prototype, from which the Fruit object inherited—all objects ultimately inherits from Object.prototype as we have noted before.​
      console.log (famousPerson.toString()); // [object Object]

    All built-in constructors (Array (), Number (), String (), etc.) were created from the Object constructor, and as such their prototype is Object.prototype.

Check back on February 7th for a quiz on JavaScript Prototype.

Additional Information
For more on JavaScript Objects, read Chapter 6 of JavaScript: The Definitive Guide (6th Edition, May 2011) by David Flanagan.

Be good. Sleep well. And enjoy coding.

JavaScript Prototype in Plain Language的更多相关文章

  1. javascript prototype原型链的原理

    javascript prototype原型链的原理 说到prototype,就不得不先说下new的过程. 我们先看看这样一段代码: <script type="text/javasc ...

  2. [原创]javascript prototype 对象 函数 <精简的美丽......>

    精简的美丽...... javascript prototype 对象 函数 在javascript中我们都知道创建一个对象使用如下代码var x = {}对象可以拥有属性和方法var x = {   ...

  3. JavaScript prototype原型用法

    JavaScript对象原型 所有JavaScript对象都从原型继承属性和方法. <!DOCTYPE html> <html> <meta charset=" ...

  4. illustrating javascript prototype & prototype chain

    illustrating javascript prototype & prototype chain 图解 js 原型和原型链 proto & prototype func; // ...

  5. JavaScript prototype原型链介绍

    javascript 是一种基于原型的编程 (prototype based programming) 的语言, 而与我们通常的基于类编程 (class based programming) 有很大的 ...

  6. HTML 学习笔记 JavaScript (prototype)

    原博地址:http://www.cnblogs.com/dolphinX/p/3286177.html 原博客的作者是一个非常牛逼的前端大神,我作为一个初学者,在此借助大神的博客进行自己的学习.在这里 ...

  7. 关于 JavaScript prototype __proto__ 一点总结

    http://www.cnblogs.com/wbin91/p/5265163.html 先上代码 function(y) Foo{ this.y = y;} Foo.prototype.x = 10 ...

  8. JavaScript prototype 使用介绍

    用过JavaScript的同学们肯定都对prototype如雷贯耳,但是这究竟是个什么东西却让初学者莫衷一是,只知道函数都会有一个prototype属性,可以为其添加函数供实例访问,其它的就不清楚了, ...

  9. JavaScript——Prototype详探

    用过JavaScript的同学们肯定都对prototype如雷贯耳,但是这究竟是个什么东西却让初学者莫衷一是,只知道函数都会有一个prototype属性,可以为其添加函数供实例访问,其它的就不清楚了, ...

随机推荐

  1. df - 报告文件系统磁盘空间的使用情况

    总览 df [OPTION]... [FILE]... POSIX 选项: [-kP] GNU 选项 (最短方式): [-ahHiklmPv] [-t fstype] [-x fstype] [--b ...

  2. 一个电脑安装两个jdk版本

    场景:先前使用了1.6的jdk但是现在学java需要使用jdk1.8的,现在打算电脑上使用两个jdk 1 . 准备两个版本的jdk我的两个jdk路径为: D:\jdk1.7.0_80 D:\Progr ...

  3. spring注解开发-扩展原理(源码)

    1.BeanFactoryPostProcessor BeanPostProcessor:bean后置处理器,bean创建对象初始化前后进行拦截工作的; BeanFactoryPostProcesso ...

  4. c++的if语句中的110为什么不等于110?

    从上图可以看出,当表达式1.1*x被直接放进if的判断括号中时1.1*x不等于y,但是将1.1*x赋值给z时,z与y相等,这是为什么?(以下为不等价时的代码) #include<stdio.h& ...

  5. Linux硬盘的检测--smartctl详细介绍

    概述  随着硬盘容量.速度的快速发展,硬盘的可靠性问题越来越重要,今天的单块硬盘存储容量可轻松达到1TB,硬盘损坏带来的影响非常巨大.不同的文件系统(xfs,reiserfs,ext3)都有自己的检测 ...

  6. 关于在views对models创建的表的简单操作

    models.User.objects.create(c1='a',c2='b') obj=models.User(c1='a',c2='b') obj.save() 增加 models.User.o ...

  7. c#导出word文档

    为方便下次遇到不知道去哪找先把它存放在这里,以下是保存导出word主要类方法 public class BiultReportForm { /// <summary>word 应用对象 & ...

  8. 使用using current logfile实现DG备库实时更新

    DG1是主库,DG2是备库:运行在最大可用模式. 实验一:未使用using current logfile参数时,备库在最大可用模式下,不能实时同步备库的更新 -此时需要等待主库进行归档---侧面证明 ...

  9. 【dp】HDU 1421 搬寝室

    http://acm.hdu.edu.cn/showproblem.php?pid=1421 [题意] 给定n个数,要从n个数中选择k个二元组{x,y},最小化sum{(x-y)^2} 2<=2 ...

  10. 【dp】E. Selling Souvenirs

    http://codeforces.com/contest/808/problem/E 题意:给定n个重量为可能1,2,3的纪念品和各自的价值,问在背包总重量不超过m的条件下总价值最大为多少. 其中1 ...