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


当前回答

(函数(){ 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'关键字。

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

在上面的例子中:

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

我希望这能说得通。

原型

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

让我用一个简单的例子来解释:

function User(email, name){
    this.email = email;
    this.name = name;
    this.online = false;
    // method directly added to the constructor
    this.greet = ()=>{
        console.log(`Hi ${this.name}`);
    }
}
// Adding prototype method login to the constructor function. 
User.prototype.login = function(){
    this.online = true;
    console.log(this.email, 'has logged in');
};
// Adding prototype method logout to the constructor function.
User.prototype.logout = function(){
    this.online = false;
    console.log(this.email, 'has logged out');
};
 
var userOne = new User('ryu@ninjas.com', 'Ryu');
var userTwo = new User('yoshi@mariokorp.com', 'Yoshi');
 
console.log(userOne);
userTwo.login();
userTwo.greet();

输出:

结论:

在构造函数中添加的属性和方法是 直接添加到对象中。 添加的属性和方法 .prototype。被添加到对象的__proto__属性中。我们甚至可以看到userOne。__proto__或userTwo.__proto__

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

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]]以及它是如何工作的。