这张图再次表明,每个对象都有一个原型。构造函数 function Foo也有自己的__proto__,也就是function .prototype, 而它又通过__proto__属性再次引用 Object.prototype。因此,重复,Foo。原型只是一个显式 Foo的属性,引用b和c对象的原型。

var b = new Foo(20);
var c = new Foo(30);

__proto__和prototype之间有什么区别?

这一数据来自dmitrysoshnikov.com网站。

注:上述2010年的文章现在有第二版(2017年)。


当前回答

原型

prototype是一个函数的属性。它是通过使用带有new关键字的that(构造函数)函数创建对象的蓝图。

__proto__

__proto__在查找链中用于解析方法、属性。当创建对象时(使用构造函数函数和new关键字),__proto__被设置为(构造函数)function .prototype

function Robot(name) {
    this.name = name;
}
var robot = new Robot();

// the following are true   
robot.__proto__ == Robot.prototype
robot.__proto__.__proto__ == Object.prototype

以下是我的(假想的)解释,以消除困惑:

假设有一个与函数相关的假想类(blueprint/ cookie cutter)。那个假想类用于实例化对象。prototype是一种扩展机制(c#或Swift Extension中的扩展方法),用于向虚类中添加内容。

function Robot(name) {
    this.name = name;
}

以上可以想象为:

// imaginary class
class Robot extends Object{

    static prototype = Robot.class  
    // Robot.prototype is the way to add things to Robot class
    // since Robot extends Object, therefore Robot.prototype.__proto__ == Object.prototype

    var __proto__;

    var name = "";

    // constructor
    function Robot(name) {

        this.__proto__ = prototype;
        prototype = undefined;

        this.name = name;
    }

} 

So,

var robot = new Robot();

robot.__proto__ == Robot.prototype
robot.prototype == undefined
robot.__proto__.__proto__ == Object.prototype

现在为Robot的原型添加方法:

Robot.prototype.move(x, y) = function(x, y){ Robot.position.x = x; Robot.position.y = y};
// Robot.prototype.move(x, y) ===(imagining)===> Robot.class.move(x, y)

以上可以想象为Robot类的扩展:

// Swift way of extention
extension Robot{
    function move(x, y){    
        Robot.position.x = x; Robot.position.y = y
    }
}

反过来,

// imaginary class
class Robot{

    static prototype = Robot.class // Robot.prototype way to extend Robot class
    var __proto__;

    var name = "";

    // constructor
    function Robot(name) {

        this.__proto__ = prototype;
        prototype = undefined;

        this.name = name;
    }

    // added by prototype (as like C# extension method)
    function move(x, y){ 
        Robot.position.x = x; Robot.position.y = y
    };
}

其他回答

另一种理解它的好方法是:

var foo = {}

/* 
foo.constructor is Object, so foo.constructor.prototype is actually 
Object.prototype; Object.prototype in return is what foo.__proto__ links to. 
*/
console.log(foo.constructor.prototype === foo.__proto__);
// this proves what the above comment proclaims: Both statements evaluate to true.
console.log(foo.__proto__ === Object.prototype);
console.log(foo.constructor.prototype === Object.prototype);

仅当支持IE11 __proto__后。在那个版本之前,比如IE9,你可以使用构造函数来获取__proto__. dll。

原型或对象。原型是一个对象文字的属性。它表示Object原型对象,您可以覆盖它以沿着原型链进一步添加更多属性或方法。

__proto__是一个访问器属性(get和set函数),它公开对象的内部原型,通过它访问对象。

引用:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/prototype http://www.w3schools.com/js/js_object_prototypes.asp https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/proto

我的理解是:__proto__和prototype都是为原型链技术服务的。区别在于以下划线命名的函数(如__proto__)根本不是开发人员显式调用的目标。换句话说,它们只是用于继承等机制,它们是“后端”。但是不带下划线的函数是为显式调用而设计的,它们是“前端”。

我碰巧从You Don't Know JS: this & Object prototyping中学习原型,这是一本很好的书,可以理解设计的底层,澄清许多误解(这就是为什么我试图避免使用继承和instanceof之类的东西)。

但我和这里的人有同样的问题。有几个答案真的很有帮助,很有启发性。我也很乐意分享我的理解。


什么是原型?

JavaScript中的对象有一个内部属性,在规范中表示为[[Prototype]],它只是对另一个对象的引用。几乎所有对象在创建时都会被赋予这个属性的非空值。

如何获得一个对象的原型?

通过__proto__或Object.getPrototypeOf

var a = { name: "wendi" };
a.__proto__ === Object.prototype // true
Object.getPrototypeOf(a) === Object.prototype // true

function Foo() {};
var b = new Foo();
b.__proto__ === Foo.prototype
b.__proto__.__proto__ === Object.prototype

原型是什么?

原型是作为函数的特殊属性自动创建的对象,用于建立委托(继承)链,即原型链。

当我们创建一个函数a时,prototype会自动作为a上的一个特殊属性创建,并将上的函数代码保存为prototype上的构造函数。

function Foo() {};
Foo.prototype // Object {constructor: function}
Foo.prototype.constructor === Foo // true

我想把这个属性作为存储函数对象的属性(包括方法)的地方。这也是JS中的实用函数被定义为Array.prototype.forEach()、Function.prototype.bind()、Object.prototype.toString()的原因。

为什么要强调函数的性质?

{}.prototype // undefined;
(function(){}).prototype // Object {constructor: function}

// The example above shows object does not have the prototype property.
// But we have Object.prototype, which implies an interesting fact that
typeof Object === "function"
var obj = new Object();

Arary, Function, Objectare都是函数。我必须承认,这刷新了我对JS的印象。我知道函数是JS中的一等公民,但它似乎是建立在函数之上的。

__proto__和prototype有什么区别?

__proto__a引用作用于每个对象以引用其[[Prototype]]属性。

Prototype是作为函数的特殊属性自动创建的对象,用于存储函数对象的属性(包括方法)。

有了这两个,我们可以在脑海中绘制出原型链。如图所示:

function Foo() {}
var b = new Foo();

b.__proto__ === Foo.prototype // true
Foo.__proto__ === Function.prototype // true
Function.prototype.__proto__ === Object.prototype // true

解释性的例子:

function Dog(){}
Dog.prototype.bark = "woof"

let myPuppie = new Dog()

现在,myPupppie有__proto__属性指向Dog.prototype。

> myPuppie.__proto__
>> {bark: "woof", constructor: ƒ}

但是mypuppy没有原型属性。

> myPuppie.prototype
>> undefined

因此,mypuppie的__proto__是对用于实例化此对象的构造函数的.prototype属性的引用(当前mypuppie对象与此__proto__对象具有“委托”关系),而mypuppie的.prototype属性则根本不存在(因为我们没有设置它)。

MPJ的解释很好: 在JavaScript中创建对象