我正在学习一些JS,我希望有人可以用简单的术语向我解释Object.getPrototypeOf()
与.prototype
function ParentClass() {}
function ChildClass() {}
ChildClass.prototype = new ParentClass();
var mychild = new ChildClass();
var myparent = new ParentClass();
# .getPrototypeOf
Object.getPrototypeOf(ChildClass.prototype) // ParentClass {}
Object.getPrototypeOf(mychild) // ParentClass {}
Object.getPrototypeOf(ParentClass.prototype) // {}
Object.getPrototypeOf(myparent) // ParentClass {}
# .prototype
ParentClass.prototype // ParentClass {}
myparent.prototype // undefined
ChildClass.prototype // ParentClass {}
mychild.prototype // undefined
所以看起来你只能在构造函数上调用.prototype?
还有其他差异吗?
答案 0 :(得分:26)
function MyConstructor() {}
var obj = new MyConstructor()
Object.getPrototypeOf(obj) === obj.prototype // false
Object.getPrototypeOf(obj) === MyConstructor.prototype // true
MyConstructor.prototype // MyConstructor {}
obj.prototype // undefined
MyConstructor.prototype.constructor === MyConstructor // true
Object.getPrototypeOf(MyConstructor) === Function.prototype // true
关于javascript中原型的令人困惑的部分是,有2种不同的东西听起来非常相似。
创建新对象时,如果用于创建新对象的函数或对象具有.prototype方法,则.prototype
引用的对象将成为新对象的原型newObj.__proto__
。 / p>
听起来很复杂......让我们进一步分解。
示例 - 使用函数作为构造函数
当您在函数上使用new
关键字时(即您将该函数用作构造函数),函数的.prototype将成为新的obj.__proto__
。
让我们先创建一个函数并签出这个.prototype属性
function MyConstructor(){
}
console.log(MyConstructor.prototype) // {}
等等...... MyConstructor.prototype // {}
- 做了什么神奇的事情?这个空对象{}
来自哪里?
这里有两件事:
只要您声明一个函数,Javascript就会自动创建一个.prototype对象 - 自动生成。
此对象不为空。它实际上有一个属性,指向创建对象的函数(对象的'构造函数')。我们来看看:
console.log(MyConstructor.prototype.constructor); // [Function: MyConstructor]
MyConstructor.prototype.constructor === MyConstructor // true
因此,对于函数,.prototype属性及其关联对象是自动创建的。
仍然困惑?让我们在那里添加一些方法,以便更容易看到发生了什么......
function MyConstructor(){
}
MyConstructor.prototype.func2 = function(){
};
console.log(MyConstructor); // [Function: MyConstructor]
console.log(MyConstructor.prototype); // MyConstructor { func2: [Function] }
MyConstructor.func2(); // TypeError: MyConstructor.func2 is not a function
显然,我们可以从上面的代码中看到MyConstructor和MyConstructor.prototype是两个独立的实体。
对象的原型(不是.prototype - 参见上面的A.)是javascript用于查找和解析对象中尚未存在的方法的内容(稍后将详细介绍)。
从上面继续,当我们从具有.prototype属性的函数或对象创建对象时,新创建的对象将使其object.__proto__
引用此.prototype对象。
可以通过
访问对象的原型 Object.getPrototypeOf(obj)
或弃用的
obj.__proto__
示例 - 使用函数作为构造函数
让我们使用MyConstructor函数作为构造函数创建一个新对象。
function MyConstructor(){
}
var obj = new MyConstructor()
console.log(Object.getPrototypeOf(obj)); // {}
以下是三个相关的事情:
obj.__proto__
- > MyConstructor.prototype 所以obj.__proto__
是MyConstructor.prototype
。以下是证据:
MyConstructor.prototype === Object.getPrototypeOf(obj) // true
让我们为MyConstructor添加一个方法
function MyConstructor(){
this.func1 = function(){
console.log("this is func1");
};
}
var obj = new MyConstructor();
obj.func1(); // this is func1
从上面你可以看到你可以调用在构造函数中声明的方法。事实上,如果我们看一下,由于javascript创建对象的方式,我们声明的方法func1实际上是obj的一部分。
console.log(obj); // MyConstructor { func1: [Function] }
我们还可以通过将方法添加到原型中来添加obj可以使用的方法。 e.g。
MyConstructor.prototype.func2 = function(){
console.log("this is func2");
};
obj.func2(); // this is func2
使用此设置,使用MyConstructor创建的所有对象都可以使用MyConstructor和MyConstructor.prototype方法。
有用的参考资料
Definitive Guide to Object-Oriented JavaScript
Understanding JavaScript: Inheritance and the prototype chain
答案 1 :(得分:1)
function Foo() {
// ...
}
var a = new Foo();
Object.getPrototypeOf( a ) === Foo.prototype; // true
通过调用a
创建new Foo()
时,发生的一件事就是a
获得了[[Prototype]]
对象的内部Foo.prototype
链接指着。
如果您真的想深入学习JavaScript,我建议您阅读"You don't know JavaScript"系列丛书。
答案 2 :(得分:0)
Object.getPrototypeOf()
与.prototype
Prototype
:javascript中的每个对象都有一个原型。这仅仅是它“继承”属性和方法的另一个对象。这个概念称为原型继承,并且是javascript中唯一的继承形式。诸如JavaScript中的class
关键字之类的构造仅仅是建立在该原型继承系统之上的语法糖。
每个函数都有一个prototype
对象属性。然后将此功能与new
关键字一起用作构造函数时,新创建的对象将从该prototype
对象继承。
Object.getPrototypeOf()
:是返回此原型对象引用的函数。我们传入一个对象作为参数,它将返回原型对象的引用。
function Dog (name) {
this.name = name;
}
// We can put properties on the prototype of the Dog constructor
Dog.prototype.bark = function () { console.log('woof'); };
let dog = new Dog('fluffie');
// Our newly created dog now has access to this bark method via the prototype chain
dog.bark();
// With the Object.getPrototypeOf method the Dog prototype object is returned
console.log(Object.getPrototypeOf(dog));
原型继承使用原型链是一个非常强大的概念。它基本上可以通过以下方式工作:
prototype
中查找。 prototype
上找不到该属性,它将爬上原型链,并查看对象prototype
对象的prototype
。这将重复直到原型链中没有更高的链(即没有更高的对象可以继承)。这具有以下优点:
Object.prototype
和Array.prototype
上有许多函数为我们提供了很多功能。例如,我们可以通过原型继承在任何数组上使用Array.prototype
的功能。答案 3 :(得分:0)
一种 prototype 是一种机制,JavaScript对象通过该机制彼此继承功能。 [1]
Object.getPrototypeOf
-这将返回给定对象的原型。 [2]
以下代码定义了一个构造函数,该函数可以通过将关键字new
放在调用之前来构建对象:
function Cat(name) {
this.name = name;
}
Cat.prototype.meow = function (sound) {
console.log(`Meow ${sound}`);
};
let cat = new Cat("Garfield");
构造函数会自动获得名为prototype
的属性,默认情况下,该属性保存一个从Object.prototype
派生的普通的空对象。可以覆盖此属性,也可以像前面的代码一样添加属性。
理解原型方法之间的区别至关重要 与构造函数(通过其原型属性)相关联,并且与 对象具有原型(可通过Object.getPrototypeOf 找到)。
构造函数的实际原型为Function.prototype
,因为构造函数
是功能。它的prototype属性保存用于实例的原型
通过它创建的。
希望在这一点上,下面的代码将使之前所说的清楚:
// This is a Cat object
> cat
Cat {name: "Garfield"}
> cat.prototype // notice that this object does not have the prototype property
undefined
// this is the constructor function
> Cat
ƒ Cat(name) {
this.name = name;
}
// this is the prototype property of a constructor
> Cat.prototype
{meow: ƒ, constructor: ƒ}
meow: ƒ (sound)
constructor: ƒ Cat(name)
__proto__: Object
// this is true as previously stated
> Object.getPrototypeOf(Cat) == Function.prototype
true
// this is true since the property prototype of a constructor is the
// prototype that objects created from it will have
> Object.getPrototypeOf(cat) == Cat.prototype
true
// Finally the prototype of the prototype property of a constructor
// is the same as Object.prototype
> Object.getPrototypeOf(Cat.prototype) == Object.prototype
true
JS类主要是对JavaScript现有的基于原型的继承的语法糖。 类语法不会向JavaScript引入新的面向对象的继承模型。
因此,Cat
的先前定义等同于以下内容:
class Cat {
constructor(name) {
this.name = name;
}
meow(sound) {
console.log(`Meow ${this.sound}`);
}
}
答案 4 :(得分:0)
@lukeaus的回答非常好。对我来说,最重要的一点是:
function MyConstructor() {} // automatically creates MyConstructor.prototype
// You can add methods to MyConstructor.prototype for objects to "inherit"
MyConstructor.prototype.foo = function() { console.log("do foo") }
// Or even reassign .prototype
// MyConstructor.prototype = { foo: function() { console.log("more foo?") } }
var obj = new MyConstructor()
Object.getPrototypeOf(obj) === MyConstructor.prototype // true
obj.foo()
因此obj的原型是MyConstructor.prototype。 MyConstructor的原型是什么?好吧,每个函数都是从Function继承而来的,所以Object.getPrototypeOf(MyConstructor) === Function.prototype
请注意,如果将.prototype分配给类似以下内容的东西,事情会变得很奇怪:
function MyConstructor() {}
MyConstructor.prototype = "foo" // make objects inherit from... a string?
var obj = new MyConstructor()
Object.getPrototypeOf(obj) === MyConstructor.prototype // false!
答案 5 :(得分:-1)
只有一个区别,方法Object.getPrototypeOf
获取对象的构造函数,然后返回其原型,而prototype
属性不执行任何操作(返回自身)。 (好吧,prototype
可以是任何东西,但如果它的对象是一个类,那么prototype
肯定应该是一个对象。)。