我对JavaScript原型概念的概念很新。
考虑以下代码:
var x = function func(){
}
x.prototype.log = function() {
console.log("1");
}
var b = new x();
据我了解,b.log()
应返回1,因为x
是其原型。但为什么属性b.prototype
未定义?
b.prototype
是否应该返回对x
函数的引用?
答案 0 :(得分:65)
只有构造函数具有原型。由于x
是构造函数,x
有原型。
b
不是构造函数。因此,它没有原型。
如果您想获得对构造b
的函数的引用(在本例中为x
),您可以使用
b.constructor
答案 1 :(得分:22)
当函数作为构造函数被调用时,函数的.prototype
属性就是在新对象上设置继承。
创建新对象时,会将其内部 [[Prototype]]
属性设置为函数.prototype
属性指向的对象。
对象本身不会获得.prototype
属性。它与对象的关系完全是内部的。
这就是b.log()
的原因。当JS引擎发现b
对象本身没有log
属性时,它会尝试在内部 [[Prototype]]
对象上查找它,并成功发现它。
要明确说明, [[Prototype]]
属性无法直接访问。它是一个内部属性,只能通过JS引擎提供的其他构造间接可变。
答案 2 :(得分:12)
在完成代码之前,我想确保理解代码行为所需的原型概念。
[[prototype]]
是JavaScript对象的隐藏属性。此隐藏属性只是指向Object.prototype
的链接(如果由对象文字创建)。没有标准方法可以访问此{{1}属性。 [[prototype]]
属性。如果是函数,则此隐藏属性是[[prototype]]
的链接。也没有标准方法来访问此{{1} }} property。Function.prototype
之外,每当创建一个函数对象时,都会在其中创建一个[[prototype]]
属性,该属性与隐藏的[[prototype]]
属性分开。现在来看你的代码:
var x = function func(){}
执行此行时,将创建一个带有两个链接的函数对象prototype
:
x.prototype.log = function(){ 的console.log(" 1&#34); }
我们现在知道[[prototype]]
是一个函数对象,因此x
是可访问的,所以在这里你可以用它包含log方法。
var b = new x();
x
是一个对象,但不是函数对象。它有隐藏的链接x.prototype
,但它无法访问。因此,当您尝试访问b
时,结果会显示[[prototype]]
。如果您想查看b.prototype
的原型而不是undefined
,则会返回b
1}}。所以你可以说隐藏的链接被引用到(x.prototype).isPrototypeOf(b);
。
以下是关于原型的一些事实:
true
创建了对象x.prototype
,那么O [[prototype]]为O
。O = new func(){}
创建了对象Function.prototype
,那么O [[prototype]]为O
。O = {}
创建了对象Object.prototype
,那么O [[prototype]]为O
。答案 3 :(得分:12)
JavaScript中的所有普通对象都有一个内部原型槽(注意:这里的原型并没有引用prototype属性)。 ECMAScript标准(http://www.ecma-international.org/ecma-262/6.0/index.html)指定此插槽称为[[Prototype]]。您可以通过__proto__属性访问此插槽。
__ proto__可能无法跨浏览器可靠地使用。 __proto__成为ECMAScript 6中的官方财产
然而,prototype属性是构造函数的一个属性,用于设置构造对象上的__proto__属性。
您可以访问某些类型的prototype属性,例如核心JavaScript类型(日期,数组等)。 JavaScript函数(可以被视为构造函数)也具有公共原型属性。但是,函数的实例没有原型属性。
在你的情况下,var b = new x();
,b是函数x的一个实例。因此b.prototype是未定义的。但是,b确实有一个内部[[Prototype]]槽。如果您在谷歌浏览器中输出b.__proto__
,例如版本63.0.3239.132,或Firefox,例如版本43.0.4
console.log(b.__proto__);
您将看到其[[Prototype]]插槽如下:
{log: ƒ, constructor: ƒ}
那就是它。
仅供您参考,整个代码段如下:
var x = function() {
};
x.prototype.log = function() {
console.log("1");
}
var b = new x();
b.log(); // 1
console.log(b.prototype); // undefined
console.log(b.__proto__); // {log: ƒ, constructor: ƒ}
console.log(x.prototype); // {log: ƒ, constructor: ƒ}
答案 4 :(得分:1)
因为prototype
是函数(实际上是构造函数)的属性,因为它定义了这个类的对象的属性/方法(那些是从这个原型所属的构造函数创建的)。看看this link