此图再次显示每个对象都有一个原型。构造函数 函数Foo也有自己的
__proto__
,它是Function.prototype, 而且它又通过其__proto__
属性再次引用 Object.prototype。因此,重复,Foo.prototype只是一个明确的 Foo的属性,指的是b和c对象的原型。
var b = new Foo(20);
var c = new Foo(30);
__proto__
和prototype
属性之间有什么区别?
该图来自here。
答案 0 :(得分:678)
__proto__
是查找链中用于解析方法等的实际对象。prototype
是使用{创建对象时用于构建__proto__
的对象{1}}:
new
答案 1 :(得分:308)
prototype
是Function对象的属性。它是由该函数构造的对象的原型。
__proto__
是对象的内部属性,指向其原型。目前的标准提供了等效的Object.getPrototypeOf(O)
方法,但事实上的标准__proto__
更快。
您可以通过将函数的instanceof
与对象的prototype
链进行比较来找到__proto__
关系,并且可以通过更改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.prototype
会保存到myPoint.__proto__
。
答案 2 :(得分:107)
声明函数时会创建Prototype属性。
例如:
function Person(dob){
this.dob = dob
};
一旦声明了上面的函数,就会在内部创建Person.prototype属性。 可以将许多属性添加到Person.prototype中,这些属性由使用新Person()创建的Person实例共享。
// adds a new method age to the Person.prototype Object.
Person.prototype.age = function(){return date-dob};
值得注意的是,Person.prototype
默认为Object
字面值(可根据需要进行更改)。
使用新Person()创建的每个实例都有一个__proto__
属性,该属性指向Person.prototype。这是用于遍历以查找特定对象的属性的链。
var person1 = new Person(somedate);
var person2 = new Person(somedate);
创建2个Person实例,这2个对象可以将Person.prototype的age属性称为person1.age,person2.age。
在上图中,您可以看到Foo是一个Function对象,因此它有一个__proto__
指向Function.prototype的链接,而该链接又是Object的一个实例,并且有一个__proto__
链接Object.prototype中。 proto链接在此结束,Object.prototype中的__proto__
指向null。
任何对象都可以访问由__proto__
链接的原型链中的所有属性,从而形成原型继承的基础。
__proto__
不是访问原型链的标准方法,标准但类似的方法是使用Object.getPrototypeOf(obj)。
以下instanceof
运算符的代码可以更好地理解:
object instanceof
当一个对象是一个Class的实例时,类运算符返回true
,更具体地说,如果在该对象的proto链中找到Class.prototype
,那么该对象就是一个实例该班级。
function instanceOf(Func){
var obj = this;
while(obj !== null){
if(Object.getPrototypeOf(obj) === Func.prototype)
return true;
obj = Object.getPrototypeOf(obj);
}
return false;
}
上述方法可以调用为:instanceOf.call(object,Class)
如果object是Class的实例,则返回true。
答案 3 :(得分:60)
想到它的好方法是......
prototype
函数使用 constructor()
。它应该被称为"prototypeToInstall"
,因为它就是它。
和__proto__
是对象的“已安装的原型”(从constructor()
函数创建/安装在对象上)
答案 4 :(得分:42)
创建函数时,会自动创建一个名为 prototype 的属性对象(您自己没有创建它)并且正在附加到函数对象(constructor
)。
注意:这个新的原型对象也指向或具有本机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;
}
如果您要使用Foo
关键字从new
创建新对象,则基本上创建一个具有内部或私有链接我们之前讨论过的函数原型Foo
:
var b = new Foo();
b.[[Prototype]] === Foo.prototype // true
<小时/> 与该函数对象的私有链接称为双括号原型或仅
[[Prototype]]
。许多浏览器都为我们提供了一个名为__proto__
的公开链接!
更具体地说,__proto__
实际上是属于本机JavaScript对象的getter function。它返回this
绑定所在的内部 - 私有原型链接(返回[[Prototype]]
的{{1}}):
b
值得注意的是,从b.__proto__ === Foo.prototype // true
开始,您还可以使用getPrototypeOf方法获取内部私有链接:
ECMAScript5
<小时/> 注意:此答案并不打算涵盖创建新对象或新构造函数的整个过程,而是为了更好地理解
Object.getPrototypeOf(b) === b.__proto__ // true
,__proto__
和{{1它是如何工作的。
答案 5 :(得分:42)
解释让我们创建一个函数
function a (name) {
this.name = name;
}
当JavaScript执行此代码时,它会将prototype
属性添加到a
,prototype
属性是一个具有两个属性的对象:
constructor
__proto__
所以当我们做的时候
a.prototype
它返回
constructor: a // function definition
__proto__: Object
现在您可以看到constructor
只是函数a
本身
并且__proto__
指向JavaScript的根级Object
。
让我们看看当a
函数与new
关键字一起使用时会发生什么。
var b = new a ('JavaScript');
当JavaScript执行此代码时,它会做4件事:
__proto__
上创建b
并指向a.prototype
所以b.__proto__ === a.prototype
a.prototype.constructor
(函数a
的定义),因此传递了name
属性因为'JavaScript'(添加到this
)被添加到新创建的对象中。b
被分配给新创建的对象。现在,如果我们添加a.prototype.car = "BMW"
并执行此操作
b.car
,输出“宝马”。
这是因为当JavaScript执行此代码时,它在car
上搜索了b
属性,但未找到使用的b.__proto__
JavaScript(指向'a.prototype) '在步骤#2中)并找到car
属性,所以返回“宝马”。
答案 6 :(得分:27)
除了上面的答案之外,还要清楚一点:
function Person(name){
this.name = name
};
var eve = new Person("Eve");
eve.__proto__ == Person.prototype //true
eve.prototype //undefined
实例有 __ proto __ ,类有原型。
答案 7 :(得分:8)
在JavaScript中,函数可以用作构造函数。这意味着我们可以使用new关键字从中创建对象。每个构造函数都带有一个与它们链接在一起的内置对象。这个内置对象称为原型。的 Instances of a constructor function use __proto__ to access the prototype property of its constructor function.
强>
首先我们创建了一个构造函数:function Foo(){}
。要清楚,Foo只是另一个功能。但我们可以使用new关键字从中创建一个对象。这就是我们称之为构造函数
每个函数都有一个唯一的属性,称为prototype属性。因此,构造函数Foo
有一个原型属性,指向其原型,Foo.prototype
(见图)。
构造函数本身就是一个函数,它是一个名为[[Function]]构造函数的系统构造函数的实例。所以我们可以说function Foo
是由[[Function]]构造函数构造的。因此,我们__proto__
的{{1}}将指向其构造函数的原型,即Foo function
。
Function.prototype
本身只不过是一个从另一个名为Function.prototype
的系统构造函数构造的对象。因此,[[Object]]
是[[Object]]
的构造函数。因此,我们可以说Function.prototype
是Function.prototype
的一个实例。因此[[Object]]
__proto__
指向Function.prototype
。
Object.prototype
是站在原型链中的最后一个人。我的意思是它还没有建成。它已经存在于系统中。因此Object.prototype
指向__proto__
。
现在我们来到null
的实例。当我们使用Foo
创建实例时,它会创建一个新对象,该对象是new Foo()
的实例。这意味着Foo
是这些实例的构造函数。这里我们创建了两个实例(x和y)。因此,Foo
x和y指向__proto__
。
答案 8 :(得分:7)
我正好从You Don't Know JS: this & Object Prototypes学习原型,这是一本很好的书,可以理解下面的设计并澄清如此多的误解(这就是为什么我试图避免使用继承和事物比如instanceof
)。
但我和人们在这里问的问题一样。几个答案真的很有帮助和启发。我也很乐意分享我的理解。
JavaScript中的对象具有内部属性,在规范中表示为[[Prototype]]
,它只是对另一个对象的引用。在创建此属性时,几乎所有对象都被赋予非null
值。
通过__proto__
或Object.getPrototypeOf
var a = { name: "wendi" };
a.__proto__ === Object.prototype // true
Object.getPrototypeOf(a) === Object.prototype // true
function Foo() {};
var b = new Foo();
b.__proto__ === Foo.prototype
b.__proto__.__proto__ === Object.prototype
prototype
? prototype
是一个自动创建的对象,作为函数的特殊属性,用于建立委托(继承)链,即原型链。
当我们创建一个函数a
时,prototype
会自动创建为a
上的特殊属性,并将函数代码保存为constructor
prototype
}。
function Foo() {};
Foo.prototype // Object {constructor: function}
Foo.prototype.constructor === Foo // true
我喜欢将此属性视为存储函数对象的属性(包括方法)的位置。这也是为什么JS中的实用函数定义为Array.prototype.forEach()
,Function.prototype.bind()
,Object.prototype.toString().
为什么要强调功能的属性?
{}.prototype // undefined;
(function(){}).prototype // Object {constructor: function}
// The example above shows object does not have the prototype property.
// But we have Object.prototype, which implies an interesting fact that
typeof Object === "function"
var obj = new Object();
因此,Arary
,Function
,Object
都是功能。我应该承认这会刷新我对JS的印象。我知道函数是JS中的一等公民,但它似乎是建立在函数之上的。
__proto__
和prototype
之间有什么区别? __proto__
引用适用于每个对象,以引用其[[Prototype]]
属性。
prototype
是一个自动创建的对象,作为函数的特殊属性,用于存储函数对象的属性(包括方法)。
通过这两个,我们可以在精神上绘制原型链。如下图所示:
function Foo() {}
var b = new Foo();
b.__proto__ === Foo.prototype // true
Foo.__proto__ === Function.prototype // true
Function.prototype.__proto__ === Object.prototype // true
答案 9 :(得分:6)
理解它的另一个好方法:
var foo = {}
/*
foo.constructor is Object, so foo.constructor.prototype is actually
Object.prototype; Object.prototype in return is what foo.__proto__ links to.
*/
console.log(foo.constructor.prototype === foo.__proto__);
// this proves what the above comment proclaims: Both statements evaluate to true.
console.log(foo.__proto__ === Object.prototype);
console.log(foo.constructor.prototype === Object.prototype);
仅支持IE11 __proto__
之后。在该版本之前,例如IE9,您可以使用constructor
获取__proto__
。
答案 10 :(得分:5)
prototype是Function的一个属性。它是使用带有new关键字的(构造函数)函数创建对象的蓝图。
__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
想象一下,有一个与功能相关的想象类(蓝图/ coockie切割器)。该虚构类用于实例化对象。 prototype
是扩展机制(C#中的扩展方法,或Swift扩展),用于向该虚构类添加内容。
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;
}
}
所以,
var robot = new Robot();
robot.__proto__ == Robot.prototype
robot.prototype == undefined
robot.__proto__.__proto__ == Object.prototype
现在将方法添加到Robot的prototype
:
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
};
}
答案 11 :(得分:4)
简单地说:
> var a = 1
undefined
> a.__proto__
[Number: 0]
> Number.prototype
[Number: 0]
> Number.prototype === a.__proto__
true
这允许您将属性附加到X.prototype AFTER类型的对象已被实例化,并且它们仍然可以通过__proto__引用访问这些新属性,Javascript引擎用它来走原型链。 / p>
答案 12 :(得分:3)
我认为您需要了解 __proto__ 、[[prototype]] 和 prototype 之间的区别。
接受的答案是有帮助的,但它可能(不完美地)暗示 __proto__
是仅与在构造函数上使用 new
创建的对象相关的东西,这不是真的。
更准确地说:__proto__
存在于每个对象上。
但是 __proto__
到底是什么?
[[prototype]]
。[[prototype]]
是 JavaScript 在内部处理的,开发人员无法访问。为什么我们需要属性 [[prototype]]
(所有对象的)的引用对象?
[[prototype]]
,所以它允许它通过一个中间层 __proto__
。因此,您可以将 __proto__
视为 [[prototype]]
属性的 getter/setter。那么 prototype
是什么?
它是特定于函数的东西(最初在Function
中定义,即Function.prototype
,然后由新原型继承 strong> 创建函数,然后这些函数再次将其提供给它们的子代,形成一个原型继承链)。
当父函数使用 prototype
运行时,JavaScript 使用父函数的 [[prototype]]
来设置其子函数的 new
(记住我们说过 all 对象有 [[prototype]]
?好吧,函数也是对象,所以它们也有 [[prototype]]
)。所以当一个函数(子)的 [[prototype]]
被设置为另一个函数(父)的 prototype
时,你最终会得到这个:
let child = new Parent();
child.__proto__ === Parent.prototype // --> true.
(记住 child.[[prototype]]
是不可访问的,所以我们使用 __proto__
检查了它。)
注意 1: 每当属性不在子级中时,它的 __proto__
将被“隐式”搜索。因此,例如,如果 child.myprop
返回一个值,您不能说“myprop”是子项的属性,还是其父项原型之一的属性。这也意味着您永远不需要自己做类似的事情:child.__proto__.__proto__.myprop
,只需 child.myprop
会自动为您做。
注意 2: 即使父级的原型中有项目,子级自己的 prototype
最初也将是一个空对象。如果您想进一步扩展继承链(将 child[ren] 添加到 child),您可以向其中添加项目或手动从中删除项目。或者它可以被隐式操作,例如,使用 class syntax。)
注意 3: __proto__
有点outdated,现代 JavaScript 建议使用 Object.setPrototypeOf
和 Object.getPrototypeOf
代替.)
答案 13 :(得分:3)
对象的__proto__
属性是映射到该对象的构造函数的prototype
的属性。换句话说:
instance.__proto__ === constructor.prototype // true
这用于形成对象的prototype
链。 prototype
链是对象属性的查找机制。如果访问了对象的属性,JavaScript将首先查看对象本身。如果在该位置找不到该属性,它将一直攀升至protochain
,直到找到(或找不到)
function Person (name, city) {
this.name = name;
}
Person.prototype.age = 25;
const willem = new Person('Willem');
console.log(willem.__proto__ === Person.prototype); // the __proto__ property on the instance refers to the prototype of the constructor
console.log(willem.age); // 25 doesn't find it at willem object but is present at prototype
console.log(willem.__proto__.age); // now we are directly accessing the prototype of the Person function
我们的第一个日志结果为true
,这是因为如上所述,构造函数创建的实例的__proto__
属性引用了构造函数的prototype
属性。请记住,在JavaScript中,函数也是对象。对象可以具有属性,任何函数的默认属性都是一个名为prototype的属性。
然后,当将此函数用作构造函数时,从该函数实例化的对象将收到一个名为__proto__
的属性。这个__proto__
属性是指构造函数的prototype
属性(默认情况下每个函数都具有)。
JavaScript在Objects
上查找属性时具有一种机制,称为“原型继承” ,这基本上是它的作用:
__proto__
属性引用的对象。在那里,它检查属性在__proto__
所引用的对象上是否可用。__proto__
对象上,它将沿着__proto__
链向上攀升,一直到Object
对象。prototype
链上任何位置的属性,它将返回undefined
。例如:
function Person (name) {
this.name = name;
}
let mySelf = new Person('Willem');
console.log(mySelf.__proto__ === Person.prototype);
console.log(mySelf.__proto__.__proto__ === Object.prototype);
答案 14 :(得分:3)
我知道,我迟到但让我试着简化它。
让我们说有一个功能
function Foo(message){
this.message = message ;
};
console.log(Foo.prototype);
Foo函数将链接原型对象。因此,每当我们在JavaScript中创建一个函数时,它总是有一个链接到它的原型对象。
现在让我们继续使用函数Foo创建两个对象。
var a = new Foo("a");
var b = new Foo("b");
console.log(a.message);
console.log(b.message);
现在,Foo.prototype,a。 proto 和b。 proto 都表示相同的对象。
b.__proto__ === Object.getPrototypeOf(a);
a.__proto__ === Foo.prototype;
a.constructor.prototype === a.__proto__;
以上所有都会返回true。
众所周知,JavaScript属性可以动态添加。我们可以添加属性到对象
Foo.prototype.Greet = function(){
console.log(this.message);
}
a.Greet();//a
b.Greet();//b
a.constructor.prototype.Greet();//undefined
如您所见,我们在Foo.prototype中添加了Greet()方法,但它可以在a和b或使用Foo构造的任何其他对象中访问。
执行a.Greet()时,JavaScript将首先在对象a属性列表中搜索Greet。如果没有找到,它将会出现在 proto 链中。由于。 proto 和Foo.prototype是同一个对象,JavaScript会找到Greet()方法并执行它。
我希望,现在原型和 proto 有点简化了。
答案 15 :(得分:3)
Prototype或Object.prototype 是对象文字的属性。它表示 Object 原型对象,您可以覆盖该对象以在原型链中进一步添加更多属性或方法。
__ proto __ 是一个访问器属性(get和set函数),它公开了访问它的对象的内部原型。
参考文献:
答案 16 :(得分:2)
(括号内的数字()是下面写的代码的“链接”)
prototype
- 包含以下内容的对象:
=&GT;功能(3)
特别是ConstructorFunction.prototype
(5),每个人都可以访问
object(4)通过这个构造函数(1)创建或创建
=&GT;构造函数本身(1)
=&GT;此特定对象的__proto__
(原型对象)
__proto__
(dandor proto?) - 通过特定构造函数(1)创建的任何对象(2)与该构造函数的原型对象属性(5)的链接BETWEEN这允许每个创建的对象(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;
答案 17 :(得分:2)
'use strict'
function A() {}
var a = new A();
class B extends A {}
var b = new B();
console.log('====='); // =====
console.log(B.__proto__ === A); // true
console.log(B.prototype.__proto__ === A.prototype); // true
console.log(b.__proto__ === B.prototype); // true
console.log(a.__proto__ === A.prototype); // true
console.log(A.__proto__ === Function.__proto__); // true
console.log(Object.__proto__ === Function.__proto__); // true
console.log(Object.prototype === Function.__proto__.__proto__); // true
console.log(Object.prototype.__proto__ === null); // true
在JavaScript中,每个对象(函数也是对象!)都有一个__proto__
属性,该属性是对其原型的引用。
当我们将new
运算符与构造函数一起使用来创建新对象时,
新对象的__proto__
属性将使用构造函数的prototype
属性进行设置,
然后构造函数将被新对象调用,
在该过程中,“ this”将在构造函数范围内引用新对象,最后返回新对象。
构造函数的原型是__proto__
属性,构造函数的prototype
属性是new
运算符的作用。
构造函数必须是一个函数,但即使具有prototype
属性,函数也不一定是构造函数。
原型链实际上是对象的__proto__
属性,用于引用其原型,
以及原型的__proto__
属性来引用原型的原型,依此类推,
直到引用Object的原型的__proto__
属性,该属性引用了null。
例如:
console.log(a.constructor === A); // true
// "a" don't have constructor,
// so it reference to A.prototype by its ``__proto__`` property,
// and found constructor is reference to A
[[Prototype]]
和__proto__
属性实际上是一回事。
我们可以使用Object的getPrototypeOf方法获取某些东西的原型。
console.log(Object.getPrototypeOf(a) === a.__proto__); // true
我们编写的任何函数都可以用于new
运算符来创建对象,
因此这些函数中的任何一个都可以成为构造函数。
答案 18 :(得分:1)
您创建的每个函数都有一个名为__proto__
的属性,它作为一个空对象开始。在使用此函数作为构造函数,即使用&#39; new&#39;之前,此属性是没用的。关键词。
这经常与对象的prototype
属性混淆。有些人可能会感到困惑,除了对象的prototype
属性可能会使它们成为对象的原型。但事实并非如此。 __proto__
用于获取从函数构造函数创建的对象的function Person(name){
this.name = name
};
var eve = new Person("Eve");
console.log(eve.__proto__ == Person.prototype) // true
// this is exactly what prototype does, made Person.prototype equal to eve.__proto__
。
在上面的例子中:
{{1}}&#13;
我希望这是有道理的。
答案 19 :(得分:1)
[[原型]]:
[[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
for..in循环和in运算符都使用[[Prototype]]链查找过程。因此,如果我们使用for..in循环来迭代对象的属性,则通过该对象的[[Prototype]]链可以达到的所有可枚举的属性也将与该对象本身的可枚举的属性一起枚举。并且当使用in运算符测试对象上是否存在属性时,in运算符将通过对象的[[Prototype]]链接检查所有属性,而不管它们的可枚举性。
// 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属性。我们知道Object.prototype是JS中所有对象的根对象。所以很明显Object是一个函数,即typeof Object ===“ function”。这意味着我们还可以通过Object函数创建对象,例如让myObj = new Object()。同样,Array,Function也是函数,因此我们可以使用Array.prototype,Function.prototype来存储数组和函数的所有常规属性。因此,我们可以说JS是基于函数构建的。
{}.prototype; // SyntaxError: Unexpected token '.'
(function(){}).prototype; // {constructor: f}
如果我们从一个函数创建对象,也要使用new运算符,然后那些新创建的对象的内部隐藏的[[Prototype]]属性将指向原始函数的.prototype属性所引用的对象。在下面的代码中,我们创建了一个对象,它来自fn,Letter和两个属性,一个添加到fn对象,另一个添加到fn的原型对象。现在,如果我们尝试访问新创建的对象的两个属性,那么我们将只能访问添加到函数原型对象的属性。这是因为该函数的原型对象现在位于新创建的对象a的[[Prototype]]链上。
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原型属性(__proto__
)实际上存在于内置Object.prototype根对象上,但可在任何特定对象上使用。我们的.__proto__
实际上是一个吸气剂/设置剂。 {。{1}}在Object.prototype中的实现如下:
.__proto__
要检索Object.defineProperty(Object.prototype, "__proto__", {
get: function() {
return Object.getPrototypeOf(this);
},
set: function(o) {
Object.setPrototypeOf(this, o);
return o;
}
});
的值就像调用,obj.__proto__
实际上返回Object.prototype对象上存在的吸气剂fn obj.__proto__()
的调用。尽管Object.getPrototypeOf(obj)
是可设置的属性,但是由于性能问题,我们不应更改现有对象的[[Prototype]]。
如果我们从函数创建对象,则使用new运算符,然后这些新创建的对象的内部隐藏的[[Prototype]]属性将指向原始函数的.prototype属性所引用的对象。使用.__proto__
属性,我们可以访问该对象的内部隐藏[[Prototype]]属性引用的其他对象。但是.__proto__
与[[Prototype]]不同,而是它的获取者/设定者。考虑下面的代码:
__proto__
答案 20 :(得分:1)
这是一个非常重要的问题,与任何想了解原型继承的人有关。据我了解,默认情况下,使用函数中的new创建对象时会分配原型,因为Function具有定义的原型对象:
function protofoo(){
}
var protofoo1 = new protofoo();
console.log(protofoo.prototype.toString()); //[object Object]
当我们创建一个没有新对象(即从函数显式)的普通对象时,它没有原型,但是有一个空的 proto ,可以为其分配原型。
var foo={
check: 10
};
console.log(foo.__proto__); // empty
console.log(bar.prototype); // TypeError
foo.__proto__ = protofoo1; // assigned
console.log(foo.__proto__); //protofoo
我们可以使用Object.create显式链接对象。
// 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`
答案 21 :(得分:1)
我为自己制作了一个小图,代表以下代码片段:
var Cat = function() {}
var tom = new Cat()
我有一个经典的OO背景,因此以这种方式表示层次结构很有帮助。为了帮助您阅读此图,请将图像中的矩形视为JavaScript对象。是的,功能也是对象。 ;)
JavaScript中的对象具有属性,__proto__
只是其中之一。
此属性背后的想法是指向(继承)层次结构中的祖先对象。
JavaScript中的根对象是Object.prototype
,所有其他对象都是该对象的后代。根对象的__proto__
属性是null
,它代表继承链的末端。
您会注意到prototype
是函数的属性。 Cat
是一个函数,但是Function
和Object
是(本机)函数。 tom
不是函数,因此不具有此属性。
此属性背后的想法是指向将在构造中使用的对象,即,当您在该函数上调用new
运算符时。
请注意,原型对象(黄色矩形)还有另一个称为
constructor
指向各自的功能对象。对于 简洁的原因未对此进行描述。
实际上,当我们使用tom
创建new Cat()
对象时,创建的对象会将__proto__
属性设置为构造函数的prototype
对象。
最后,让我们玩一下此图。以下陈述是正确的:
tom.__proto__
属性指向与Cat.prototype
相同的对象。
Cat.__proto__
指向Function.prototype
对象,就像Function.__proto__
和Object.__proto__
一样。
Cat.prototype.__proto__
和tom.__proto__.__proto__
指向同一个对象,即Object.prototype
。
干杯!
答案 22 :(得分:1)
说明性示例:
function Dog(){}
Dog.prototype.bark = "woof"
let myPuppie = new Dog()
现在,myPupppie具有指向Dog.prototype的__proto__
属性。
> myPuppie.__proto__
>> {bark: "woof", constructor: ƒ}
但是myPuppie没有原型属性。
> myPuppie.prototype
>> undefined
因此,mypuppie的__proto__
是对用于实例化此对象的构造函数的.prototype属性的引用(并且当前myPuppie对象具有与“代理”的关系)这个__proto__
对象),而myPuppie的.prototype属性完全不存在(因为我们没有设置它)。
MPJ的很好解释: proto vs prototype - Object Creation in JavaScript
答案 23 :(得分:1)
__proto__
是构造prototype
的基础和构造函数,例如:function human(){}
具有prototype
,该__proto__
在新实例中通过OutDir
共享。构造函数。更详细的阅读here
答案 24 :(得分:1)
我会尝试四年级的解释:
事情很简单。 prototype
是应该如何构建某个东西的示例。所以:
我是function
,我构建的新对象类似于我的prototype
我是object
我是以我的__proto__
为例构建的
<强>证据强>:
function Foo() { }
var bar = new Foo()
// `bar` is constructed from how Foo knows to construct objects
bar.__proto__ === Foo.prototype // => true
// bar is an instance - it does not know how to create objects
bar.prototype // => undefined
答案 25 :(得分:0)
(function(){
let a = function(){console.log(this.b)};
a.prototype.b = 1;
a.__proto__.b = 2;
let q = new a();
console.log(a.b);
console.log(q.b)
})()
尝试此代码以了解
答案 26 :(得分:0)
正如this正确陈述的那样
__proto__
是在查找链中用于 解析方法等。prototype是用于构建的对象__proto__
用新的对象创建时:( new Foo ).__proto__ === Foo.prototype; ( new Foo ).prototype === undefined;
我们还可以注意到,使用函数构造函数创建的对象的__proto__
属性指向该相应构造函数的 prototype 属性所指向的内存位置。
如果我们更改构造函数的 prototype 的存储位置,则派生对象的__proto__
仍将继续指向原始地址空间。因此,要使公用属性在继承链中可用,请始终将属性附加到构造函数 prototype 中,而不是重新初始化它(这会更改其内存地址)。
考虑以下示例:
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
答案 27 :(得分:0)
只有一个对象用于原型链接。该对象显然具有名称和值:firebase
是其名称,而__proto__
是其值。就是这样。
为使其更容易理解,请查看这篇文章顶部的图表(Dmitgram by dmitry soshnikov),您将找不到prototype
指向__proto__
以外的其他地方,因为它的价值。
要点是:prototype
是引用原型对象的名称,而__proto__
是实际的原型对象。
这就像在说:
prototype
var x = {name: 'john'};
是对象名称(指针),而x
是实际对象(数据值)。
注意:这只是在很大程度上简化了它们之间的关联的提示。
答案 28 :(得分:0)
如何将__proto__
用于静态方法?
function Foo(name){
this.name = name
Foo.__proto__.collection.push(this)
Foo.__proto__.count++
}
Foo.__proto__.count=0
Foo.__proto__.collection=[]
var bar = new Foo('bar')
var baz = new Foo('baz')
Foo.count;//2
Foo.collection // [{...}, {...}]
bar.count // undefined
答案 29 :(得分:-1)
我的理解是:__ proto__和原型都是为原型链技术服务的。不同之处在于使用下划线命名的函数(如__proto__)并不是开发人员明确调用的目标。换句话说,它们只是用于继承等机制,它们是后端的。但是没有下划线命名的函数是为明确调用而设计的,它们是前端&#39;。
答案 30 :(得分:-3)
!!!这是世界上最好的解释!!!!!
var q = {}
var prototype = {prop: 11}
q.prop // undefined
q.__proto__ = prototype
q.prop // 11
在函数构造函数中,当我们编写q.__proto__ = prototype
时,javascript引擎会自动调用此new Class
,并进入__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
享受%)