为什么在新对象上未定义JavaScript原型属性?

时间:2013-01-22 02:43:32

标签: javascript prototype

我对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函数的引用?

5 个答案:

答案 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)

在完成代码之前,我想确保理解代码行为所需的原型概念。

  1. [[prototype]]是JavaScript对象的隐藏属性。此隐藏属性只是指向Object.prototype的链接(如果由对象文字创建)。没有标准方法可以访问此{{1}属性。
  2. JavaScript中的函数是对象,因此它们也具有[[prototype]]属性。如果是函数,则此隐藏属性是[[prototype]]的链接。也没有标准方法来访问此{{1} }} property。
  3. 除了此隐藏链接Function.prototype之外,每当创建一个函数对象时,都会在其中创建一个[[prototype]]属性,该属性与隐藏的[[prototype]]属性分开。
  4. 现在来看你的代码:

      

    var x = function func(){}

    执行此行时,将创建一个带有两个链接的函数对象prototype

    • Function.prototype(不可访问),
    • x.prototype(access)。
      

    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);

    以下是关于原型的一些事实:

    1. 如果使用true创建了对象x.prototype,那么O [[prototype]]为O
    2. 如果使用O = new func(){}创建了对象Function.prototype,那么O [[prototype]]为O
    3. 如果使用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