0x9*_*x90 730 javascript prototype prototypal-inheritance javascript-objects
该图再次显示每个对象都有一个原型.构造函数Foo也有自己
__proto__的Function.prototype,它又通过其__proto__属性再次引用到Object.prototype.因此,重复,Foo.prototype只是Foo的一个显式属性,它指的是b和c对象的原型.
var b = new Foo(20);
var c = new Foo(30);
Run Code Online (Sandbox Code Playgroud)
__proto__和prototype属性有什么区别?

这个数字来自这里.
Mar*_*ahn 712
__proto__是在查找链中用于解析方法的实际对象,等等 prototype是在__proto__创建对象时用于构建的对象new:
( new Foo ).__proto__ === Foo.prototype;
( new Foo ).prototype === undefined;
Run Code Online (Sandbox Code Playgroud)
Imp*_*Imp 320
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;
Run Code Online (Sandbox Code Playgroud)
这Point是一个构造函数,它在程序上构建一个对象(数据结构).myPoint是一个由Point()so 构造的对象Point.prototype,myPoint.__proto__在那时被保存到.
小智 113
声明函数时会创建Prototype属性.
例如:
function Person(dob){
this.dob = dob
};
Run Code Online (Sandbox Code Playgroud)
一旦声明了上面的函数,就会在内部创建Person.prototype属性.可以将许多属性添加到Person.prototype中,这些属性由使用新Person()创建的Person实例共享.
// adds a new method age to the Person.prototype Object.
Person.prototype.age = function(){return date-dob};
Run Code Online (Sandbox Code Playgroud)
值得注意的Person.prototype是Object,默认情况下是一个文字(可以根据需要进行更改).
使用新Person()创建的每个实例都有一个new Person()指向Person.prototype 的属性.这是用于遍历以查找特定对象的属性的链.
var person1 = new Person(somedate);
var person2 = new Person(somedate);
Run Code Online (Sandbox Code Playgroud)
创建2个Person实例,这2个对象可以将Person.prototype的age属性称为person1.age,person2.age.
在上图中,您可以看到Foo是一个Function对象,因此它有一个__proto__指向Function.prototype 的链接,而Function.prototype又是Object的一个实例,并且有一个Person.prototype指向Object.prototype 的链接.proto链接Person在Object.prototype中指向null.
任何对象都可以访问其原型链中的所有属性age,从而形成原型继承的基础.
Person.prototype 不是访问原型链的标准方法,标准但类似的方法是使用Object.getPrototypeOf(obj).
以下代码为person1.age运算符提供了更好的理解:
object person2.age类操作符Foo在对象是Class的实例时返回,更具体地说,如果Function Object在该对象的proto链中找到该对象,则该对象是该Class的实例.
function instanceOf(Func){
var obj = this;
while(obj !== null){
if(Object.getPrototypeOf(obj) === Func.prototype)
return true;
obj = Object.getPrototypeOf(obj);
}
return false;
}
Run Code Online (Sandbox Code Playgroud)
上面的方法可以调用为:__proto__如果object是Class的实例,则返回true.
sar*_*ink 62
想到它的好方法是......
prototype由constructor()函数使用.它应该被称为类似的东西"prototypeToInstall",因为它就是它的本质.
并且__proto__是对象的"已安装的原型"(从所述constructor()函数创建/安装在对象上)
Man*_*z90 53
为了解释让我们创建一个函数
function a (name) {
this.name = name;
}
Run Code Online (Sandbox Code Playgroud)
当JavaScript执行此代码时,它会向其添加prototype属性a,prototypeproperty是一个具有两个属性的对象:
constructor__proto__所以,当我们这样做
a.prototype 它返回
constructor: a // function definition
__proto__: Object
Run Code Online (Sandbox Code Playgroud)
现在你可以看到constructor只是函数a本身,并__proto__指向ObjectJavaScript 的根级别.
让我们看看当我们使用关键词a功能时会发生什么new.
var b = new a ('JavaScript');
Run Code Online (Sandbox Code Playgroud)
当JavaScript执行此代码时,它会做4件事:
__proto__于b并使其指向a.prototype这样b.__proto__ === a.prototypea.prototype.constructor(函数的定义a),因此name作为"JavaScript"(添加到this)的属性被添加到新创建的对象中.b被分配给新创建的对象.现在,如果我们添加a.prototype.car = "BMW"并执行
b.car,输出"BMW"就会出现.
这是因为当JavaScript执行此代码时,它搜索car属性b,它没有找到使用的JavaScript b.__proto__(在步骤#2中指向'a.prototype')并找到car属性所以返回"BMW".
Lio*_*rom 45
在创建函数时,会自动创建一个名为prototype的属性对象(您自己没有创建它)并且正在附加到函数对象(the 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;
}
Run Code Online (Sandbox Code Playgroud)
如果您将Foo使用new关键字创建一个新对象,您基本上创建(除其他外)一个新对象,该对象具有我们之前讨论过的函数原型的内部或私有链接Foo:
var b = new Foo();
b.[[Prototype]] === Foo.prototype // true
Run Code Online (Sandbox Code Playgroud)
[[Prototype]].很多浏览器都为我们提供了一个公共链接,它叫做__proto__!
更具体地说,__proto__实际上是属于本机JavaScript对象的getter函数.它返回无论内部和私营部门的原型联动this的结合是(返回[[Prototype]]的b):
b.__proto__ === Foo.prototype // true
Run Code Online (Sandbox Code Playgroud)
值得注意的是,启动时ECMAScript5,您还可以使用getPrototypeOf方法获取内部私有链接:
Object.getPrototypeOf(b) === b.__proto__ // true
Run Code Online (Sandbox Code Playgroud)
__proto__,prototype和[[Prototype]]它是如何工作的.
ser*_*kan 29
除了上面的答案之外,还要清楚一点:
function Person(name){
this.name = name
};
var eve = new Person("Eve");
eve.__proto__ == Person.prototype //true
eve.prototype //undefined
Run Code Online (Sandbox Code Playgroud)
实例有__proto__,类有原型.
ade*_*hox 17
我认为你需要知道__proto__、[[prototype]]和prototype之间的区别。
接受的答案是有帮助的,但它可能意味着(不完美)这__proto__仅与使用构造函数创建的对象相关new,但事实并非如此。
更准确地说:__proto__存在于每个对象上。
但__proto__到底是什么?
[[prototype]]。[[prototype]]这是 JavaScript 在内部处理的事情,开发人员无法访问。[[prototype]]为什么我们需要一个(所有对象的)属性的引用对象?
[[prototype]]直接获取/设置,所以它允许通过中间层__proto__. 所以你可以将其视为属性__proto__的 getter/setter [[prototype]]。那是什么prototype?
它是特定于函数的东西(最初在Functionie 中定义,Function.prototype然后由新创建的函数原型继承,然后这些函数再次将其传递给它们的子函数,形成原型继承链)。
当父函数运行时,JavaScript 使用父函数prototype来设置其子函数(记住我们说过所有对象都有?好吧,函数也是对象,所以它们也有)。因此,当一个函数(子函数)的 被设置为另一个函数(父函数)的 时,最终会得到这样的结果:[[prototype]]new[[prototype]][[prototype]][[prototype]]prototype
let child = new Parent();
child.__proto__ === Parent.prototype // --> true.
Run Code Online (Sandbox Code Playgroud)
(记住child.[[prototype]]无法访问,所以我们使用 检查它__proto__。)
注意 1:只要子属性不存在,__proto__就会“隐式”搜索它。因此,例如,如果child.myprop返回一个值,您无法判断“myprop”是否是子级的属性,或其父级原型之一的属性。这也意味着您永远不需要做这样的事情:child.__proto__.__proto__.myprop您自己,只会child.myprop自动为您做这件事。
注意2:即使父级的原型中有项目,子级自己的原型prototype最初也将是一个空对象。如果您想进一步扩展继承链(将 child[ren] 添加到子项),您可以手动向其中添加或删除项目。或者可以隐式操作它,例如使用类语法。)
注意 3:如果您需要[[prototype]]自己设置/获取,使用__proto__有点过时了,现代 JavaScript 建议使用Object.setPrototypeOfandObject.getPrototypeOf代替。
AL-*_*ami 12
在JavaScript中,函数可以用作构造函数.这意味着我们可以使用new关键字从中创建对象.每个构造函数都带有一个与它们链接在一起的内置对象.这个内置对象称为原型.Instances of a constructor function use __proto__ to access the prototype property of its constructor function.
首先我们创建了一个构造函数:function Foo(){}.要清楚,Foo只是另一个功能.但我们可以使用new关键字从中创建一个对象.这就是我们称之为构造函数的原因
每个函数都有一个唯一的属性,称为prototype属性.因此,Constructor函数Foo有一个原型属性,指向其原型,即Foo.prototype(见图).
构造函数本身就是一个函数,它是一个名为[[Function]]构造函数的系统构造函数的实例.所以我们可以说它function Foo是由[[Function]]构造函数构造的.因此,__proto__我们的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.这意味着Foo是这些实例的构造函数.这里我们创建了两个实例(x和y).__proto__因此,x和y指向Foo.prototype.
'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
Run Code Online (Sandbox Code Playgroud)
在 JavaScript 中,每个对象(函数也是对象!)都有一个 __proto__属性,该属性是对其原型的引用。
当我们使用new带有构造函数的运算符来创建一个新对象时,新对象的__proto__属性将被设置为构造函数的prototype属性,然后构造函数将被新对象调用,在这个过程中“this”将成为对新对象的引用在构造函数作用域中,最终返回新对象。
构造函数的原型是__proto__属性,构造函数的prototype属性是与new操作符。
构造函数必须是函数,但函数并不总是构造函数,即使它有 prototype属性。
原型链实际上是对象的__proto__属性引用其原型,原型的__proto__属性引用原型的原型,以此类推,直到引用对象的原型__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
Run Code Online (Sandbox Code Playgroud)
[[Prototype]]和__proto__财产实际上是一回事。
我们可以使用 Object 的 getPrototypeOf 方法来获取某物的原型。
console.log(Object.getPrototypeOf(a) === a.__proto__); // true
Run Code Online (Sandbox Code Playgroud)
我们编写的任何函数都可以用来创建带有new运算符的对象,因此这些函数中的任何一个都可以是构造函数。
考虑下面的代码:
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
Run Code Online (Sandbox Code Playgroud)
我们可以用下图来描述上面的代码:
现在让我们详细探讨[[Prototype]]一下:__proto__prototype
[[Prototype]][[Prototype]]是JS中对象的内部隐藏属性,它是对另一个对象的引用。每个对象在创建时都会收到一个对象(或 null)作为[[Prototype]]。当我们引用对象上的属性时[[Get]],就会调用像myObject.a. 如果对象本身具有属性,a则将使用该属性。
let myObject = {
a: 2,
};
console.log(myObject.a); // 2
Run Code Online (Sandbox Code Playgroud)
但如果对象本身不直接具有所请求的属性,则[[Get]]操作将继续沿着[[Prototype]]对象的链接进行。此过程将继续,直到找到匹配的属性名称或[[Prototype]]链结束(在内置Object.prototype)。如果没有找到匹配的属性,undefined则将返回。现在Object.create(anyObject)创建一个具有[[Prototype]]到指定 的链接的对象anyObject。
let anotherObject = {
a: 2,
};
// create an object linked to anotherObject
let myObject = Object.create(anotherObject);
console.log(myObject.a); // 2
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
__proto____proto__是 JS 中对象的属性,它引用链中的另一个对象[[Prototype]]。我们知道[[Prototype]]JS 中对象的内部隐藏属性,它引用链中的另一个对象[[Prototype]]。[[Prototype]]我们可以通过两种方式获取或设置内部属性引用的对象
Object.getPrototypeOf(obj) / Object.setPrototypeOf(obj)
obj.__proto__
我们可以[[Prototype]]使用以下方式遍历链: .__proto__.__proto__. .。随着.constructor,.toString(),.isPrototypeOf()。dunder proto 属性 ( __proto__) 实际上存在于内置Object.prototype根对象中,但可在任何特定对象上使用。__proto__实际上是一个 getter/setter。__proto__in的实现Object.prototype如下:
Object.defineProperty(Object.prototype, "__proto__", {
get: function () {
return Object.getPrototypeOf(this);
},
set: function (o) {
Object.setPrototypeOf(this, o);
return o;
},
});
Run Code Online (Sandbox Code Playgroud)
检索 的值obj.__proto__就像调用一样,实际上返回的是对象上存在的obj.__proto__()getter fn 的调用。虽然是一个可设置的属性,但由于性能问题,我们不应该更改已经存在的对象。Object.getPrototypeOf(obj)Object.prototype__proto__[[Prototype]]
new如果我们从函数创建对象,则使用运算符,那么[[Prototype]]这些新创建的对象的内部隐藏属性将指向prototype原始函数的属性引用的对象。使用属性,我们可以访问由对象的__proto__内部隐藏属性引用的其他对象。[[Prototype]]但与它的 getter/setter 不同__proto__。[[Prototype]]
prototypeprototype是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
*/
Run Code Online (Sandbox Code Playgroud)
但JS中的普通对象没有prototype属性。我们知道Object.prototype是JS中所有对象的根对象。很明显Object是一个函数 ie typeof Object === "function"。这意味着我们还可以从函数创建一个对象Object,例如let myObj= new Object(). 同样Array,Function也是函数,因此我们可以使用Array.prototype,Function.prototype来存储数组和函数的所有通用属性。这意味着我们可以说 JS 是建立在函数之上的。
{}.prototype; // SyntaxError: Unexpected token '.'
(function(){}).prototype; // {constructor: f}
Run Code Online (Sandbox Code Playgroud)
new如果我们从函数创建对象,那么也使用运算符,那么[[Prototype]]这些新创建的对象的内部隐藏属性将指向prototype原始函数的属性引用的对象。在下面的代码中,我们obj从 fn 创建了一个对象,Letter并添加了 2 个属性,一个添加到 fn 对象,另一个添加到 fn 的原型对象。现在,如果我们尝试访问新创建的对象上的两个属性,obj那么我们只能访问添加到函数原型对象中的属性。这是因为函数的原型对象现在位于[[Prototype]]新创建的对象的链上obj。
let Letter = function () {};
let obj = new Letter();
Letter.from = "Albuquerque";
Letter.prototype.to = "New Hampshire";
console.log(obj.from); // undefined
console.log(obj.to); // New Hampshire
Run Code Online (Sandbox Code Playgroud)
小智 7
我知道,我迟到了,但让我试着简化一下。
假设有一个函数
function Foo(message){
this.message = message ;
};
console.log(Foo.prototype);
Run Code Online (Sandbox Code Playgroud)
Foo 函数将链接一个原型对象。因此,每当我们在 JavaScript 中创建一个函数时,它总是有一个链接到它的原型对象。
现在让我们继续使用函数 Foo 创建两个对象。
var a = new Foo("a");
var b = new Foo("b");
console.log(a.message);
console.log(b.message);
Run Code Online (Sandbox Code Playgroud)
现在,Foo.prototype、a.__proto__ 和 b.__proto__ 都表示同一个对象。
b.__proto__ === Object.getPrototypeOf(a);
a.__proto__ === Foo.prototype;
a.constructor.prototype === a.__proto__;
Run Code Online (Sandbox Code Playgroud)
以上所有内容都会返回 true。
众所周知,JavaScript 中的属性可以动态添加。我们可以给对象添加属性
Foo.prototype.Greet = function(){
console.log(this.message);
}
a.Greet();//a
b.Greet();//b
a.constructor.prototype.Greet();//undefined
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,我们在 Foo.prototype 中添加了 Greet() 方法,但可以在 a 和 b 或使用 Foo 构造的任何其他对象中访问它。
当执行 a.Greet() 时,JavaScript 将首先在对象 a 的属性列表中搜索 Greet。如果找不到,它将进入 a 的 __proto__ 链。由于 a.__proto__ 和 Foo.prototype 是同一个对象,JavaScript 将找到 Greet() 方法并执行它。
我希望,现在原型和 __proto__ 被简化了一些。
我碰巧学习了你不知道JS的原型:这个和对象原型,这是一本很好的书,可以理解下面的设计并澄清如此多的误解(这就是为什么我试图避免使用继承等等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
Run Code Online (Sandbox Code Playgroud)
prototype?prototype是一个自动创建的对象,它是一个函数的特殊属性,用于建立委托(继承)链,即原型链.
当我们创建一个函数时a,prototype会自动创建一个特殊属性a并将函数代码保存为constructoron prototype.
function Foo() {};
Foo.prototype // Object {constructor: function}
Foo.prototype.constructor === Foo // true
Run Code Online (Sandbox Code Playgroud)
我很乐意将此属性视为存储函数对象的属性(包括方法)的位置.这也是为什么在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();
Run Code Online (Sandbox Code Playgroud)
所以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
Run Code Online (Sandbox Code Playgroud)
的__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 Run Code Online (Sandbox Code Playgroud)
我们的第一个日志结果为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);Run Code Online (Sandbox Code Playgroud)
理解它的另一个好方法:
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);
Run Code Online (Sandbox Code Playgroud)
仅在__proto__支持IE11之后.在那个版本之前,比如IE9,你可以用它constructor来获取__proto__.
我为自己制作了一个小图,表示以下代码片段:
var Cat = function() {}
var tom = new Cat()
Run Code Online (Sandbox Code Playgroud)
我有经典的面向对象背景,因此以这种方式表示层次结构很有帮助。为了帮助您阅读此图,请将图像中的矩形视为 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__do 一样。
Cat.prototype.__proto__并tom.__proto__.__proto__指向同一个对象,即Object.prototype。
干杯!
prototype是Function的属性。这是通过使用带有new关键字的(构造函数)功能创建对象的蓝图。
__proto__在查找链中用于解析方法,属性。创建对象时(使用带有new关键字的构造函数),__proto__设置为(Constructor)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
Run Code Online (Sandbox Code Playgroud)
想象有一个与功能相关的假想类(蓝图/库奇刀具)。该虚构类用于实例化对象。prototype是将事物添加到该虚构类的扩展机制(C#或Swift扩展中的扩展方法)。
function Robot(name) {
this.name = name;
}
Run Code Online (Sandbox Code Playgroud)
以上可以想象为:
// 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;
}
}
Run Code Online (Sandbox Code Playgroud)
所以,
var robot = new Robot();
robot.__proto__ == Robot.prototype
robot.prototype == undefined
robot.__proto__.__proto__ == Object.prototype
Run Code Online (Sandbox Code Playgroud)
现在向prototypeRobot的方法添加方法:
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)
Run Code Online (Sandbox Code Playgroud)
以上可以想象为Robot类的扩展:
// Swift way of extention
extension Robot{
function move(x, y){
Robot.position.x = x; Robot.position.y = y
}
}
Run Code Online (Sandbox Code Playgroud)
反过来,
// 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
};
}
Run Code Online (Sandbox Code Playgroud)