这张图再次表明,每个对象都有一个原型。构造函数 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是Function对象的一个属性。它是由该函数构造的对象的原型。

__proto__是一个对象的内部属性,指向它的原型。当前标准提供了等效的Object.getPrototypeOf(obj)方法,尽管事实上的标准__proto__更快。

你可以通过比较函数的原型和对象的__proto__链来找到instanceof关系,你也可以通过改变prototype来打破这些关系。

function Point(x, y) {
    this.x = x;
    this.y = y;
}

var myPoint = new Point();

// the following are all true
myPoint.__proto__ == Point.prototype
myPoint.__proto__.__proto__ == Object.prototype
myPoint instanceof Point;
myPoint instanceof Object;

这里Point是一个构造函数,它程序化地构建一个对象(数据结构)。myPoint是一个由Point()构造的对象,所以Point。原型保存到myPoint。解析:句意:在那个时候。

其他回答

[[原型]]:

[[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

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

!!!这是世界上最好的解释!!!!!

var q = {}
var prototype = {prop: 11}

q.prop // undefined
q.__proto__ = prototype
q.prop // 11

在函数构造函数中,当我们编写新Class时,javascript引擎会自动调用这个q.__proto__ = prototype,并在__proto__道具中设置Class.prototype

function Class(){}
Class.prototype = {prop: 999} // set prototype as we need, before call new

var q = new Class() // q.__proto__ = Class.prototype
q.prop // 999

享受%)

我认为你需要知道__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代替。

正如这句话所说

__proto__是用于查找链的实际对象 原型是用来构建的对象 当你用new创建一个对象时: (新的Foo)。__proto__ === Foo.prototype; (新的Foo)。原型=== undefined;

我们可以进一步注意到,使用函数构造函数创建的对象的__proto__属性指向相应构造函数的prototype属性所指向的内存位置。

如果我们改变构造函数的prototype的内存位置,派生对象的__proto__仍将继续指向原始地址空间。因此,要使公共属性沿着继承链向下可用,总是将属性附加到构造函数函数原型,而不是重新初始化它(这会改变它的内存地址)。

考虑下面的例子:

function Human(){
    this.speed = 25;
}

var himansh = new Human();

Human.prototype.showSpeed = function(){
    return this.speed;
}

himansh.__proto__ === Human.prototype;  //true
himansh.showSpeed();    //25

//now re-initialzing the Human.prototype aka changing its memory location
Human.prototype = {lhs: 2, rhs:3}

//himansh.__proto__ will still continue to point towards the same original memory location. 

himansh.__proto__ === Human.prototype;  //false
himansh.showSpeed();    //25