__proto__ VS. prototype in JavaScript
This figure again shows that every object has a prototype. Constructor
function Foo also has its own__proto__ which is Function.prototype,
and which in turn also references via its__proto__ property again to
the Object.prototype. Thus, repeat, Foo.prototype is just an explicit
property of Foo which refers to the prototype of b and c objects.
1 2 | var b = new Foo(20); var c = new Foo(30); |
这个数字来自这里。
1 2 | ( new Foo ).__proto__ === Foo.prototype; ( new Foo ).prototype === undefined; |
您可以通过将函数的
1 2 3 4 5 6 7 8 9 10 11 12 | 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; |
这里
声明函数时会创建Prototype属性。
例如:
1 2 3 | function Person(dob){ this.dob = dob }; |
一旦声明了上面的函数,就会在内部创建Person.prototype属性。
可以将许多属性添加到Person.prototype中,这些属性由使用新Person()创建的Person实例共享。
1 2 | // adds a new method age to the Person.prototype Object. Person.prototype.age = function(){return date-dob}; |
值得注意的是,默认情况下
使用
1 2 | var person1 = new Person(somedate); var person2 = new Person(somedate); |
创建
在您问题的上图中,您可以看到
任何对象都可以访问其原型链中由
下面的
object
1 2 3 4 5 6 7 8 9 | function instanceOf(Func){ var obj = this; while(obj !== null){ if(Object.getPrototypeOf(obj) === Func.prototype) return true; obj = Object.getPrototypeOf(obj); } return false; } |
上面的方法可以被称为:
想到它的好方法是......
和
为了解释让我们创建一个函数
1 2 3 | function a (name) { this.name = name; } |
当JavaScript执行此代码时,它会将
所以,当我们这样做
1 2 | constructor: a // function definition __proto__: Object |
现在你可以看到
和
让我们看看当我们使用
1 | var b = new a ('JavaScript'); |
当JavaScript执行此代码时,它会做4件事:
现在,如果我们添加
这是因为当JavaScript执行此代码时,它在
原型VS. __proto__ VS. [[原型]]
在创建函数时,会自动创建一个名为prototype的属性对象(您自己没有创建它)并且正在附加到函数对象(
例:
1 2 3 4 5 6 7 8 9 10 11 12 | 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; } |
如果你将使用
1 2 3 | var b = new Foo(); b.[[Prototype]] === Foo.prototype // true |
该函数对象的私有链接称为双括号原型或只是
更具体地说,
1 | b.__proto__ === Foo.prototype // true |
值得注意的是,从
1 | Object.getPrototypeOf(b) === b.__proto__ // true |
注意:这个答案并不打算涵盖创建新对象或新构造函数的整个过程,而是为了帮助更好地理解
除了上面的答案之外,还要清楚一点:
1 2 3 4 5 6 7 8 9 | function Person(name){ this.name = name }; var eve = new Person("Eve"); eve.__proto__ == Person.prototype //true eve.prototype //undefined |
实例有__proto__,类有原型。
在JavaScript中,函数可以用作构造函数。这意味着我们可以使用new关键字从中创建对象。每个构造函数都带有一个与它们链接在一起的内置对象。这个内置对象称为原型。
首先我们创建了一个构造函数:
每个函数都有一个唯一的属性,称为prototype属性。因此,构造函数
构造函数本身就是一个函数,它是一个名为[[Function]]构造函数的系统构造函数的实例。所以我们可以说
现在我们来到
我碰巧学习了你不知道JS的原型:这个&对象原型,这是一本很好的书,可以理解下面的设计并澄清如此多的误解(这就是为什么我试图避免使用继承和
但我有同样的问题,就像人们在这里问的那样。几个答案真的很有帮助和启发。我也很想分享我的理解。
什么是原型?
JavaScript中的对象具有内部属性,在规范中表示为
如何获得对象的原型?
via
1 2 3 4 5 6 7 8 | 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 |
什么是
当我们创建一个函数
1 2 3 | function Foo() {}; Foo.prototype // Object {constructor: function} Foo.prototype.constructor === Foo // true |
我很乐意将此属性视为存储函数对象的属性(包括方法)的位置。这也是为什么JS中的实用程序函数被定义为
为什么要强调函数的属性?
1 2 3 4 5 6 7 | {}.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(); |
所以,
有了这两个,我们就可以在精神上绘制原型链。如下图所示:
1 2 3 4 5 6 | function Foo() {} var b = new Foo(); b.__proto__ === Foo.prototype // true Foo.__proto__ === Function.prototype // true Function.prototype.__proto__ === Object.prototype // true |
理解它的另一个好方法:
1 2 3 4 5 6 7 8 9 10 | 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
原型
prototype是Function的一个属性。它是使用带有new关键字的(构造函数)函数创建对象的蓝图。
__proto__
在查找链中使用
1 2 3 4 5 6 7 8 | function Robot(name) { this.name = name; } var robot = new Robot(); // the following are true robot.__proto__ == Robot.prototype robot.__proto__.__proto__ == Object.prototype |
这是我(假想的)解释清除混乱:
想象一下,有一个与功能相关的想象类(蓝图/ coockie切割器)。该虚构类用于实例化对象。
1 2 3 | function Robot(name) { this.name = name; } |
以上可以想象为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | // 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; } } |
所以,
1 2 3 4 5 | var robot = new Robot(); robot.__proto__ == Robot.prototype robot.prototype == undefined robot.__proto__.__proto__ == Object.prototype |
现在添加方法到机器人的
1 2 | 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类的扩展:
1 2 3 4 5 6 | // Swift way of extention extension Robot{ function move(x, y){ Robot.position.x = x; Robot.position.y = y } } |
反过来,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | // 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 }; } |
摘要:
对象的
这用于形成对象的
例:
1 2 3 4 5 6 7 8 9 10 11 12 | 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 |
我们的第一个日志结果是
然后,当此函数用作构造函数时,从其实例化的对象将接收名为
为什么这有用?
查找
- 首先,检查属性是否位于Object本身。如果是,则返回此属性。
-
如果属性不在对象本身上,它将"爬上原始链接"。它基本上是查看
__proto__ 属性引用的对象。在那里,它检查属性是否在__proto__ 引用的对象上可用。 -
如果属性不在
__proto__ 对象上,它将爬上__proto__ 链,一直到Object 对象。 -
如果它无法在对象及其
prototype 链的任何位置找到该属性,则它将返回undefined 。
例如:
1 2 3 4 5 6 7 8 9 | function Person (name) { this.name = name; } let mySelf = new Person('Willem'); console.log(mySelf.__proto__ === Person.prototype); console.log(mySelf.__proto__.__proto__ === Object.prototype); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | '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中,每个对象(函数也是对象!)都有一个
当我们使用
新对象的
那么构造函数将被新对象调用,
在那个进程中"this"将是对构造函数作用域中新对象的引用,最后返回新对象。
构造函数的原型是
构造函数必须是一个函数,但即使函数具有
原型链实际上是对象的
和原型的
直到引用Object的原型的
例如:
1 2 3 4 | 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 |
我们可以使用Object的getPrototypeOf方法来获取原型。
1 | console.log(Object.getPrototypeOf(a) === a.__proto__); // true |
我们编写的任何函数都可用于使用
所以这些函数中的任何一个都可以是构造函数。
简而言之:
1 2 3 4 5 6 7 8 | > var a = 1 undefined > a.__proto__ [Number: 0] > Number.prototype [Number: 0] > Number.prototype === a.__proto__ true |
这允许您将属性附加到X.prototype AFTER类型的对象已被实例化,并且他们仍然可以通过__proto__引用访问这些新属性,Javascript引擎用它来走原型链。
Prototype或Object.prototype是对象文字的属性。它表示Object原型对象,您可以覆盖它以在原型链中进一步添加更多属性或方法。
__proto__是一个访问器属性(get和set函数),它公开了访问它的对象的内部原型。
参考文献:
http://www.w3schools.com/js/js_object_prototypes.asp
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/proto
我知道,我迟到但让我试着简化它。
让我们说有一个功能
1 2 3 4 5 6 | function Foo(message){ this.message = message ; }; console.log(Foo.prototype); |
Foo函数将链接原型对象。因此,每当我们在JavaScript中创建一个函数时,它总是有一个链接到它的原型对象。
现在让我们继续使用函数Foo创建两个对象。
1 2 3 4 | var a = new Foo("a"); var b = new Foo("b"); console.log(a.message); console.log(b.message); |
使用构造函数Foo。请记住构造函数在这里只是一个词。
现在,Foo.prototype,a.proto和b.proto都表示相同的对象。
1 2 3 | b.__proto__ === Object.getPrototypeOf(a); a.__proto__ === Foo.prototype; a.constructor.prototype === a.__proto__; |
以上所有都将返回true。
众所周知,JavaScript属性可以动态添加。我们可以添加属性到对象
1 2 3 4 5 6 7 | 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。如果没有找到,它将会进入原型链。由于a.proto和Foo.prototype是同一个对象,JavaScript会找到Greet()方法并执行它。
我希望,现在原型和proto有点简化了。
定义
(括号()内的数字是下面写的代码的"链接")
=>函数(3)
特别是
object(4)通过这个构造函数创建或创建(1)
=>构造函数本身(1)
=>
代码澄清
1。
1 2 3 4 | function Person (name, age) { this.name = name; this.age = age; ? } |
2。
1 2 | var John = new Person(‘John’, 37); // John is an object |
3。
1 2 3 4 | Person.prototype.getOlder = function() { this.age++; } // getOlder is a key that has a value of the function |
4。
1 | John.getOlder(); |
5。
1 | Person.prototype; |
您创建的每个函数都有一个名为
这通常与对象的
在上面的例子中:
1 2 3 4 5 6 7 8 | 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 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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 |
1 2 3 4 5 6 7 8 | (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) })() |
试试这段代码吧
解释性的例子:
1 2 3 4 | function Dog(){} Dog.prototype.bark ="woof" let myPuppie = new Dog() |
现在,myPupppie具有
1 2 | > myPuppie.__proto__ >> {bark:"woof", constructor: ?} |
但myPuppie没有原型属性。
1 2 | > myPuppie.prototype >> undefined |
因此,mypuppie的
MPJ在这里做了很好的解释:
proto vs prototype - JavaScript中的对象创建
我会尝试四年级的解释:
事情很简单。
-
我是
function ,我构建了类似于我的prototype 的新对象 -
我是
object ,我使用__proto__ 作为示??例构建
证明:
1 2 3 4 5 6 7 8 9 | 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 |
正如这正确地指出的那样
__proto__ is the actual object that is used in the lookup chain to
resolve methods, etc. prototype is the object that is used to build
__proto__ when you create an object with new:
1
2 ( new Foo ).__proto__ === Foo.prototype;
( new Foo ).prototype === undefined;
我们还可以注意到,使用函数构造函数创建的对象的
如果我们更改构造函数原型的内存位置,派生对象的
请考虑以下示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | 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 |
我的理解是:__ proto__和原型都是为原型链技术服务的。不同之处在于使用下划线命名的函数(如__proto__)并不是开发人员明确调用的目标。换句话说,它们只是用于继承等机制,它们是"后端"。但是没有下划线命名的函数是为明确调用而设计的,它们是'前端'。
!!!这是世界上最好的解释!!!!!
1 2 3 4 5 6 | var q = {} var prototype = {prop: 11} q.prop // undefined q.__proto__ = prototype q.prop // 11 |
在函数构造函数中,当我们编写
1 2 3 4 5 | 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 |
请享用 %)