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


当前回答

正如这句话所说

__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

其他回答

(函数(){ Let a = function(){console.log(this.b)}; A.prototype.b = 1; a.__proto__。B = 2; 设q = new a(); console.log (a.b); console.log (q.b) }) ()

试着理解这段代码

原型

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

对于任何想要了解原型继承的人来说,这都是一个非常重要的问题。根据我的理解,默认情况下,当从函数中使用new创建对象时,prototype会被赋值,因为function定义了prototype对象:

function protofoo(){
}
var protofoo1 = new protofoo();
console.log(protofoo.prototype.toString()); //[object Object]

当我们创建一个普通的对象,没有new,即显式地从一个函数,它没有原型,但它有一个空的原型,可以分配一个原型。

var foo={
  check: 10
};
console.log(foo.__proto__); // empty
console.log(bar.prototype); //  TypeError
foo.__proto__ = protofoo1; // assigned
console.log(foo.__proto__); //protofoo

我们可以使用Object。创建以显式链接对象。

// we can create `bar` and link it to `foo`
var bar = Object.create( foo );
bar.fooprops= "We checking prototypes";
console.log(bar.__proto__); // "foo"
console.log(bar.fooprops); // "We checking prototypes"
console.log(bar.check); // 10 is delegated to `foo`

简介:

对象的__proto__属性是映射到该对象的构造函数原型的属性。换句话说:

实例。__proto__ ===构造函数。原型// true

这用于形成对象的原型链。原型链是一个对象属性的查找机制。如果访问对象的属性,JavaScript将首先查看对象本身。如果属性在那里没有找到,它将一路攀升到原链,直到它被找到(或没有)

例子:

人(姓名、城市){ This.name = name; } Person.prototype.age = 25; const willem =新人(' willem '); console.log(威廉。__proto__ === Person.prototype);//实例上的__proto__属性指向构造函数的原型 console.log (willem.age);// 25没有在willem object中找到它,但在prototype中存在 console.log (willem.__proto__.age);//现在我们直接访问Person函数的原型

第一个日志的结果为true,这是因为构造函数创建的实例的__proto__属性引用了构造函数的prototype属性。记住,在JavaScript中,函数也是对象。对象可以有属性,任何函数的默认属性都是一个名为prototype的属性。

然后,当这个函数被用作构造函数时,从它实例化的对象将接收一个名为__proto__的属性。这个__proto__属性引用了构造函数的prototype属性(默认情况下每个函数都有)。

为什么这个有用?

JavaScript在查找对象属性时有一种叫做“原型继承”的机制,下面是它的基本功能:

First, it's checked if the property is located on the Object itself. If so, this property is returned. If the property is not located on the object itself, it will 'climb up the protochain'. It basically looks at the object referred to by the __proto__ property. There, it checks if the property is available on the object referred to by __proto__. If the property isn't located on the __proto__ object, it will climb up the __proto__ chain, all the way up to Object object. If it cannot find the property anywhere on the object and its prototype chain, it will return undefined.

例如:

人(名){ This.name = name; } let mySelf =新人(“威廉”); console.log(我自己。__proto__ === Person.prototype); console.log (mySelf.__proto__。__proto__ === Object.prototype);

您创建的每个函数都有一个称为prototype的属性,它开始时是一个空对象。这个属性是没有用处的,直到你使用这个函数作为构造函数,即与'new'关键字。

这经常与对象的__proto__属性相混淆。有些人可能会感到困惑,除了对象的原型属性可能会让他们得到对象的原型。但事实并非如此。Prototype用于获取由函数构造函数创建的对象的__proto__。

在上面的例子中:

函数的人(名字){ This.name = name }; var eve =新人(“eve”); console.log(夏娃。__proto__ == Person.prototype) // true //这就是prototype所做的,Person。Prototype等于eve.__proto__

我希望这能说得通。