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


当前回答

定义

(括号()内的数字是一个“链接”到下面写的代码)

原型-一个对象,包括: =>函数(3) prototype(5) 通过此构造函数(1)创建或将创建的对象(4) =>构造函数本身(1) =>此特定对象的__proto__ (prototype对象)

__proto__ (dandor prototype ?) -通过特定构造函数(1)创建的任何对象(2)和该构造函数的原型对象的属性(5)之间的链接,允许每个创建的对象(2)访问原型的函数和方法(4)(__proto__默认包含在JS中的每个对象中)

代码说明

1.

    function Person (name, age) {
        this.name = name;
        this.age = age;  

    } 

2.

    var John = new Person(‘John’, 37);
    // John is an object

3.

    Person.prototype.getOlder = function() {
        this.age++;
    }
    // getOlder is a key that has a value of the function

4.

    John.getOlder();

5.

    Person.prototype;

其他回答

简单来说:

> var a = 1
undefined
> a.__proto__
[Number: 0]
> Number.prototype
[Number: 0]
> Number.prototype === a.__proto__
true

这允许你在X类型的对象实例化之后将属性附加到X.prototype,并且它们仍然可以通过javascript引擎使用的__proto__引用访问这些新属性。

[[原型]]:

[[Prototype]]是JS中对象的内部隐藏属性,它是对另一个对象的引用。每个对象在创建时都会接收一个非空值[[Prototype]]。请记住,当我们引用对象上的属性(如myObject.a)时调用[[Get]]操作。如果对象本身有一个属性,那么该属性将被使用。

let myObject= {
    a: 2
};

console.log(myObject.a);            // 2

但是如果对象本身直接没有所请求的属性,那么[[Get]]操作将继续遵循对象的[[Prototype]]链接。这个过程将继续进行,直到找到匹配的属性名或[[Prototype]]链结束(在内置的Object.prototype处)。如果没有找到匹配的属性,则返回undefined。object. create(specifiedObject)创建一个带有[[Prototype]]链接到指定对象的对象。

let anotherObject= {
    a: 2
};

// create an object linked to anotherObject
let myObject= Object.create(anotherObject);
console.log(myObject.a);                // 2

Both for..in loop and in operator use [[Prototype]] chain lookup process. So if we use for..in loop to iterate over the properties of an object then all the enumerable properties which can be reached via that object's [[Prototype]] chain also will be enumerated along with the enumerable properties of the object itself. And when using in operator to test for the existence of a property on an object then in operator will check all the properties via [[Prototype]] linkage of the object regardless of their enumerability.

// for..in loop uses [[Prototype]] chain lookup process
let anotherObject= {
    a: 2
};

let myObject= Object.create(anotherObject);

for(let k in myObject) {
    console.log("found: " + k);            // found: a
}

// in operator uses [[Prototype]] chain lookup process
console.log("a" in myObject);              // true

.prototype:

.prototype是JS中函数的一个属性,它引用了一个具有构造函数属性的对象,该对象存储了函数对象的所有属性(和方法)。

let foo= function(){}

console.log(foo.prototype);        
// returns {constructor: f} object which now contains all the default properties

foo.id= "Walter White";

foo.job= "teacher";

console.log(foo.prototype);       
// returns {constructor: f} object which now contains all the default properties and 2 more properties that we added to the fn object
/*
{constructor: f}
    constructor: f()
        id: "Walter White"
        job: "teacher"
        arguments: null
        caller: null
        length: 0
        name: "foo"
        prototype: {constructor: f}
        __proto__: f()
        [[FunctionLocation]]: VM789:1
        [[Scopes]]: Scopes[2]
    __proto__: Object

*/

但是JS中的普通对象没有.prototype属性。我们知道客体。prototype是JS中所有对象的根对象。所以很明显Object是一个函数,即typeof Object === "function"。这意味着我们还可以从object函数创建对象,比如let myObj= new object()。类似地,Array, Function也是函数,所以我们可以使用Array。原型,函数。用于存储数组和函数的所有通用属性的原型。所以我们可以说JS是建立在函数之上的。

{}.prototype;                            // SyntaxError: Unexpected token '.'

(function(){}).prototype;                // {constructor: f}

Also using new operator if we create objects from a function then internal hidden [[Prototype]] property of those newly created objects will point to the object referenced by the .prototype property of the original function. In the below code, we have created an object, a from a fn, Letter and added 2 properties one to the fn object and another to the prototype object of the fn. Now if we try to access both of the properties on the newly created object, a then we only will be able to access the property added to the prototype object of the function. This is because the prototype object of the function is now on the [[Prototype]] chain of the newly created object, a.

let Letter= function(){}

let a= new Letter();

Letter.from= "Albuquerque";

Letter.prototype.to= "New Hampshire";

console.log(a.from);                // undefined

console.log(a.to);                  // New Hampshire

.__proto__:

.__proto__是JS中对象的属性,它引用[[Prototype]]链中的另一个对象。我们知道[[Prototype]]是JS中对象的内部隐藏属性,它引用了[[Prototype]]链中的另一个对象。我们可以通过两种方式获取或设置内部[[Prototype]]属性引用的对象

Object.getPrototypeOf(obj) / Object.setPrototypeOf(obj) obj.__proto__

我们可以使用.__proto__.__proto__遍历[[Prototype]]链。与.constructor, . tostring (), . isprototypeof()一起,我们的dunder prototo属性(__proto__)实际上存在于内置对象中。原型根对象,但可用于任何特定对象。我们的.__proto__实际上是一个getter/setter。Object中.__proto__的实现。原型如下:

Object.defineProperty(Object.prototype, "__proto__", {
    get: function() {
        return Object.getPrototypeOf(this);
    },
    set: function(o) {
        Object.setPrototypeOf(this, o);
        return o;
    }
});

检索obj的值。__proto__类似于调用,obj.__proto__(),它实际上返回了getter fn, Object. getprototypeof (obj),它存在于Object上。原型对象。虽然.__proto__是一个可设置的属性,但由于性能问题,我们不应该更改已经存在的对象的[[Prototype]]。

如果使用new操作符从函数创建对象,那么这些新创建对象的内部隐藏[[Prototype]]属性将指向原始函数的. Prototype属性引用的对象。使用.__proto__属性,我们可以访问由对象的内部隐藏[[Prototype]]属性引用的另一个对象。但是__proto__并不等同于[[Prototype]],而是它的getter/setter。考虑下面的代码:

let Letter= function() {}

let a= new Letter();

let b= new Letter();

let z= new Letter();

// output in console
a.__proto__ === Letter.prototype;               // true

b.__proto__ === Letter.prototype;               // true

z.__proto__ === Letter.prototype;               // true

Letter.__proto__ === Function.prototype;        // true

Function.prototype.__proto__ === Object.prototype;        // true

Letter.prototype.__proto__ === Object.prototype;          // true

Prototype VS. __proto__ VS. [[Prototype]]

在创建函数时,会自动创建一个名为prototype的属性对象(不是您自己创建的),并将其附加到函数对象(构造函数)。注意:这个新的原型对象也指向本机JavaScript对象,或者有一个内部私有链接。

例子:

function Foo () {
    this.name = 'John Doe';
}

// Foo has an object property called prototype.
// prototype was created automatically when we declared the function Foo.
Foo.hasOwnProperty('prototype'); // true

// Now, we can assign properties and methods to it:
Foo.prototype.myName = function () {
    return 'My name is ' + this.name;
}

如果你使用new关键字从Foo中创建一个新对象,你基本上是在创建一个新对象,它有一个内部或私有的链接到我们之前讨论过的函数Foo的原型:

var b = new Foo();

b.[[Prototype]] === Foo.prototype  // true

到该函数对象的私有链接称为双括号prototype或[[prototype]]。许多浏览器为我们提供了一个公共链接,称为__proto__!

更具体地说,__proto__实际上是一个属于原生JavaScript对象的getter函数。它返回this绑定的内部私有原型链接(返回b的[[prototype]]):

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

值得注意的是,ECMAScript5的启动,你也可以使用getPrototypeOf方法来获得内部的私有链接:

Object.getPrototypeOf(b) === b.__proto__ // true

注意:这个答案并不打算涵盖创建新对象或新构造函数的整个过程,而是帮助更好地理解__proto__、prototype和[[prototype]]以及它是如何工作的。

原型

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

原型或对象。原型是一个对象文字的属性。它表示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