这张图再次表明,每个对象都有一个原型。构造函数 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年)。


当前回答

为了解释,让我们创建一个函数

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

当JavaScript执行这段代码时,它将prototype属性添加到。prototype属性是一个具有两个属性的对象:

构造函数 __proto__

所以当我们这样做的时候

a.原型它返回

     constructor: a  // function definition
    __proto__: Object

现在你可以看到构造函数就是函数a本身 而__proto__指向JavaScript的根对象。

让我们看看当我们使用带有new关键字的函数时会发生什么。

var b = new a ('JavaScript');

当JavaScript执行这段代码时,它会做4件事:

它创建了一个新对象,一个空对象// {} 它在b上创建__proto__,并使其指向a.prototype,因此b.__proto__ === a.prototype 它使用新创建的对象(在步骤#1中创建)作为上下文(this)执行a.p otype.constructor(这是函数a的定义),因此作为'JavaScript'传递的name属性(它被添加到this)被添加到新创建的对象。 它返回新创建的对象(在步骤#1中创建),因此var b被分配给新创建的对象。

现在如果我们添加a.prototype。car = "BMW"然后 b.car,输出“BMW”出现。

这是因为当JavaScript执行这段代码时,它在b上搜索car属性,它没有发现,然后JavaScript使用b.__proto__(在步骤#2中指向“a.prototype”)并找到car属性,因此返回“BMW”。

其他回答

在声明函数时创建Prototype属性。

例如:

 function Person(dob){
    this.dob = dob
 }; 

的人。Prototype属性在声明上述函数后在内部创建。 可以向Person添加许多属性。由使用new Person()创建的Person实例共享的原型。

// adds a new method age to the Person.prototype Object.
Person.prototype.age = function(){return date-dob}; 

值得注意的是,Person。prototype默认是Object字面量(可以根据需要更改)。

使用new Person()创建的每个实例都有一个指向Person.prototype的__proto__属性。这是用于遍历查找特定对象的属性的链。

var person1 = new Person(somedate);
var person2 = new Person(somedate);

创建2个Person实例,这2个对象可以调用Person的age方法。原型作为人物1。年龄,person2.age。

在你的问题的上图中,你可以看到Foo是一个函数对象,因此它有一个__proto__链接到函数。prototype是Object的一个实例,并且有一个指向Object.prototype的__proto__链接。原型链接在这里以对象中的__proto__结束。原型指向null。

任何对象都可以访问其原型链中的所有属性,通过__proto__链接,从而形成原型继承的基础。

__proto__不是访问原型链的标准方法,标准但类似的方法是使用Object.getPrototypeOf(obj)。

下面的instanceof操作符代码提供了更好的理解:

当一个对象是一个类的实例时,更具体地说,如果Class,则返回true。prototype是在该对象的原型链中找到的,那么该对象就是该类的实例。

function instanceOf(Func){
  var obj = this;
  while(obj !== null){
    if(Object.getPrototypeOf(obj) === Func.prototype)
      return true;
    obj = Object.getPrototypeOf(obj);
  }
  return false;
}      

上面的方法可以调用为:instanceOf。调用(object, Class),如果object是Class的实例则返回true。

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

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。

原型

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
    };
}

我认为你需要知道__proto__, [[prototype]]和prototype之间的区别。

公认的答案是有帮助的,但它可能暗示(不完全)__proto__只与在构造函数上使用new创建的对象相关,这是不正确的。

更准确地说:__proto__存在于每个对象上。

But what is __proto__ at all? Well, it is an object referencing another object which is also a property of all objects, called [[prototype]]. It's worth mentioning that [[prototype]] is something that JavaScript handles internally and is inaccessible to the developer. Why would we need a reference object to the property [[prototype]] (of all objects)? Because JavaScript doesn't want to allow getting / setting the [[prototype]] directly, so it allows it through a middle layer which is __proto__. So you can think of __proto__ as a getter/setter of the [[prototype]] property. What is prototype then? It is something specific to functions(Initially defined in Function, i.e, Function.prototype and then prototypically inherited by newly created functions, and then again those functions give it to their children, forming a chain of prototypical inheritance). JavaScript uses a parent function's prototype to set its child functions' [[prototype]] when that parent function is run with new (remember we said all objects have [[prototype]]? well, functions are objects too, so they have [[prototype]] as well). So when the [[prototype]] of a function(child) is set to the prototype of another function(parent), you will have this in the end: let child = new Parent(); child.__proto__ === Parent.prototype // --> true. (Remember child.[[prototype]] is inaccessible, so we checked it using __proto__.)


注意1:只要属性不在子对象中,它的__proto__将被“隐式”搜索。例如,if child。Myprop返回一个值,你不能说" Myprop "是子对象的属性,还是父对象原型的属性。这也意味着你永远不需要做这样的事情:child.__proto__.__proto__。我的东西你自己拿去吧,孩子。Myprop会自动为你做这件事。

注意2:即使父对象的原型中有项目,子对象自己的原型最初也是一个空对象。如果您想进一步扩展继承链(将child[ren]添加到child),则可以向其中添加项或手动从其中删除项。或者可以隐式地操纵它,例如使用类语法。)

注意3:如果你需要自己设置/获取[[prototype]],使用__proto__有点过时,现代JavaScript建议使用Object。setPrototypeOf和Object。getPrototypeOf代替。

我碰巧从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