为什么在新对象上未定义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函数的引用?

只有构造函数有原型。 由于x是构造函数,所以x有一个原型。

b不是一个构造函数。 因此,它没有一个原型。

如果你想获得一个构造b的函数的引用(在本例中是x ),你可以使用

 b.constructor 

函数的.prototype属性就是在函数被调用作为构造函数时,在新对象上设置inheritance的地方。

当新对象被创build时,它的内部[[Prototype]]属性被设置为函数的.prototype属性指向的对象。

该对象本身不会得到一个.prototype属性。 它与对象的关系是完全内部的。

这就是为什么它能够做b.log() 。 当JS引擎发现b对象本身没有log属性时,它会尝试在对象internal [[Prototype]]对象上查找它,并在其中成功find它。

要清楚, [[Prototype]]属性不能直接访问。 这是一个内部属性,只能通过JS引擎提供的其他结构间接变化。

在通过你的代码之前,我想确定一些理解代码行为所需的原型概念。

  1. [[prototype]]是一个JavaScript对象的隐藏属性。这个隐藏的属性不过是一个到Object.prototype的链接(如果由对象文字创build)。没有标准的方法来访问这个[[prototype]]属性。
  2. JavaScript中的函数是对象,所以它们也具有[[prototype]]属性。这里,在函数的情况下,这个隐藏的属性是一个到Function.prototype的链接。也没有标准的方法来访问这个[[prototype]]属性。
  3. 除了这个隐藏的链接[[prototype]] ,每当一个函数对象被创build,一个prototype属性被创build,它与隐藏的[[prototype]]属性是分开的。

现在来到你的代码:

var x = function func(){}

当这行执行时,一个函数对象x用两个链接创build:

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

x.prototype.log = function(){console.log(“1”); }

因为我们现在知道x是一个函数对象,所以x.prototype是可访问的,所以在这里你可以包含log方法。

var b = new x();

b是一个对象而不是函数对象,它有隐藏的链接[[prototype]]但是不可访问。 所以当你尝试像b.prototype一样b.prototype它会给出undefined的结果。如果你想检查b的原型,你可以看到(x.prototype).isPrototypeOf(b); 它会返回true 。 所以你可以说隐藏的链接引用了x.prototype

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

  1. 如果使用O = new func(){}创build对象O而不是O [[prototype]]是Function.prototype
  2. 如果使用O = {}创build对象O而不是O [[prototype]]是Object.prototype
  3. 如果用O = Object.create(obj)创build的对象O比O [[prototype]]是obj

JavaScript中的每个对象都有一个原型(注意:这里的原型并不是指原型属性)。 ECMAScript标准( http://www.ecma-international.org/ecma-262/6.0/index.html )指定该属性被称为[[Prototype]]。 您可以通过两种方式访问​​该属性:非标准__proto__属性和prototype属性。

__proto__在浏览器中可能不可靠。 __proto__成为ECMAScript 6中的官方属性

您还可以访问某些types的原型属性,例如,核心JavaScripttypes(date,数组等)。 另外一个JavaScript函数(可以被看作构造函数)有一个公共的prototype属性。 但是,函数的实例没有原型属性。

在你的情况下,b.prototype是未定义的,但如果你输出在Firefox如43.0.4版本

 console.log(b.__proto__); 

你会看到它的[[Prototype]]属性如下:

 func { log=function()} 

因为prototype是函数(实际上是构造函数)的一个属性,因为它定义了这个类的对象的属性/方法(这些是从这个原型的构造函数创build的)。 看看这个链接