说到prototype,就不得不先说下new的过程。

我们先看看这样一段代码:

<script type="text/javascript">
var Person = function () { };
var p = new Person();
</script>


 

很简单的一段代码,我们来看看这个new究竟做了什么?我们可以把new的过程拆分成以下三步:

<1> var p={}; 也就是说,初始化一个对象p。

<2> p.__proto__=Person.prototype; 2个下划线+proto+2个下划线

<3> Person.call(p);也就是说构造p,也可以称之为初始化p。

关键在于第二步,我们来证明一下:

 

<script type="text/javascript">
var Person = function () { };
var p = new Person();
alert(p.__proto__ === Person.prototype);
</script>


这段代码会返回true。说明我们步骤2的正确。

那么__proto__是什么?我们在这里简单地说下。每个对象都会在其内部初始化一个属性,就是__proto__,当我们访问一个对象的属性时,如果这个对象内部不存在这个属性,那么他就会去__proto__里找这个属性,这个__proto__又会有自己的__proto__,于是就这样一直找下去,也就是我们平时所说的原型链的概念。

按照标准,__proto__是不对外公开的,也就是说是个私有属性,但是Firefox的引擎将他暴露了出来成为了一个共有的属性,我们可以对外访问和设置。

好,概念说清了,让我们看一下下面这些代码:

 

<script type="text/javascript">
var Person = function () { };
Person.prototype.Say = function () {
alert("Person say");
}
var p = new Person();
p.Say();
</script>


这段代码很简单,相信每个人都这样写过,那就让我们看下为什么p可以访问Person的Say。

首先var p=new Person();可以得出p.__proto__=Person.prototype。那么当我们调用p.Say()时,首先p中没有Say这个属性,于是,他就需要到他的__proto__中去找,也就是Person.prototype,而我们在上面定义了Person.prototype.Say=function(){}; 于是,就找到了这个方法。

好,接下来,让我们看个更复杂的。



var Person = function () { };
Person.prototype.Say = function () {
alert("Person say");
}
Person.prototype.Salary = 50000;
var Programmer = function () { };
Programmer.prototype = new Person();
Programmer.prototype.WriteCode = function () {
alert("programmer writes code");
};
Programmer.prototype.Salary = 500;
var p = new Programmer();
p.Say();
p.WriteCode();
alert(p.Salary);


们来做这样的推导:

var p=new Programmer()可以得出p.__proto__=Programmer.prototype;

而在上面我们指定了Programmer.prototype=new Person();我们来这样拆分,

var p1=new Person();Programmer.prototype=p1;那么:

p1.__proto__=Person.prototype;

Programmer.prototype.__proto__=Person.prototype; ..

Programmer.prototype = new Person();


 

由根据上面得到p.__proto__=Programmer.prototype。可以得到p.__proto__.__proto__=Person.prototype。

好,算清楚了之后我们来看上面的结果,p.Say()。由于p没有Say这个属性,于是去p.__proto__,也就是Programmer.prototype,也就是p1中去找,由于p1中也没有Say,那就去p.__proto__.__proto__,也就是Person.prototype中去找,于是就找到了alert(“Person say”)的方法。

其余的也都是同样的道理。

这也就是原型链的实现原理。

最后,其实prototype只是一个假象,他在实现原型链中只是起到了一个辅助作用,换句话说,他只是在new的时候有着一定的价值,而原型链的本质,其实在于__proto__!

 

转自:http://www.cnblogs.com/kym/archive/2010/01/09/1643062.html


 

另外一篇:

An Object's ​​__proto__​​ property references the same object as its internal ​​[[Prototype]]​​ (often referred to as "the prototype"), which may be an object or ​​null ​​(in the case of ​​Object.prototype.__proto__​​). This property is an abstraction error, because a property with the same name, but some other value, could be defined on the object too. If there is a need to reference an object's prototype, the preferred method is to use ​​Object.getPrototypeOf​​.

 

var proto = obj.__proto__;


When an object is created, its ​​__proto__​​ property is set to reference the same object as its internal ​​[[Prototype]]​​ (i.e. its constructor's ​​prototype​​ object).  Assigning a new value to ​​__proto__​​ also changes the value of the internal ​​[[Prototype]]​​ property, except where the object is non–extensible.

当1个对象创建时,__proto__属性被设置于引用相同的【prototype】对象。赋一个值给__proto__属性会改变【prototype】属性,除非对象不可扩展。

To understand how prototypes are used for inheritance, see the MDN article ​​Inheritance and the prototype chain​​.

Example

In the following, a new instance of ​​Employee​​ is created, then tested to show that its ​​__proto__​​ is the same object as its constructor's ​​prototype​​.




// Declare a function to be used as a constructor

function Employee() {

/* initialise instance */

}


// Create a new instance of Employee

var fred = new Employee();


// Test equivalence

fred.__proto__ === Employee.prototype; // true


At this point, ​​fred​​ inherits from ​​Employee​​, however assigning a different object to ​​fred.__proto__​​ can change that:




1


2




​// Assign a new object to __proto__​


​fred.__proto__ = Object.prototype;​



Now ​​fred​​ no longer inherits from ​​Employee.prototype​​, but directly from ​​Object.prototype​​, and loses the properties it originally inherited from ​​Employee.prototype​​.

However, this only applies to ​​extensible​​ objects, a non–extensible object's ​​__proto__​​ property cannot be changed:




1


2


3


4




​var​​ ​​obj = {};​


​Object.preventExtensions(obj);​


 


​obj.__proto__ = {}; ​​​​// throws a TypeError​



 一篇很好的文章:

转自: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 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.(设置__proto__为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!

转:javascript prototype原型链的原理_sed

另外一篇好文:

http://dmitrysoshnikov.com/ecmascript/javascript-the-core/