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

其他回答

__proto__是在查找链中用于解析方法的实际对象,prototype是在你用new创建对象时用于构建__proto__的对象:

( new Foo ).__proto__ === Foo.prototype
( new Foo ).prototype === undefined

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

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

在上面的例子中:

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

我希望这能说得通。

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。解析:句意:在那个时候。

我为自己画了一个小图,代表以下代码片段:

var Cat = function() {}
var tom = new Cat()

我有经典的OO背景,所以用这种方式表示层次结构很有帮助。为了帮助您阅读此图表,请将图像中的矩形视为JavaScript对象。是的,函数也是对象。;)

JavaScript中的对象有属性,__proto__只是其中之一。

此属性背后的思想是指向(继承)层次结构中的祖先对象。

JavaScript的根对象是object。Prototype和所有其他对象都是这个对象的后代。根对象的__proto__属性为null,表示继承链的结束。

你会注意到原型是函数的属性。Cat是一个函数,但function和Object也是(本机)函数。Tom不是一个函数,因此它没有这个属性。

此属性背后的思想是指向一个将在构造中使用的对象,即当您在该函数上调用new操作符时。

注意,原型对象(黄色矩形)有另一个属性称为 构造函数,它指向各自的函数对象。为 简短的原因,这是没有描述。

实际上,当我们用new Cat()创建tom对象时,所创建的对象的__proto__属性将被设置为构造函数的原型对象。

最后,让我们稍微研究一下这个图表。以下陈述是正确的:

汤姆。__proto__属性指向与Cat.prototype相同的对象。 猫。__proto__指向函数。原型对象,就像函数一样。__proto__和Object。__proto__做。 Cat.prototype。__proto__和tom.__proto__。__proto__指向相同的对象,即object .prototype。

干杯!

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