数字营销 · Web开发 · 基础设施

为什么实例化的对象没有prototype属性

从一个简单的实例化示例出发,理解 JavaScript 构造函数与实例对象之间 prototype 的区别。

问题来源于这里:

<script>
function Human(){
this.height =180;

this.say =function(){
alert("我在说话");
}
}

var he=newHuman();

alert(Human.prototype); // Object
alert(he.prototype); // undefined
</script>

为什么 Human.prototype 是存在的,而 he.prototype 却是 undefined

其实说起来比较简单。

prototype 是函数对象用于构造实例时使用的一个属性。也就是说,我们通常关注的是构造函数的 prototype,而通过构造函数创建出来的实例对象,并不会因此自动拥有一个同名的 prototype 属性。

所以 Human.prototype 存在,而 he.prototype 不存在。

这也就是之前文章中第一个没有弄明白的问题。

JavaScript 中的构造器

为了彻底弄明白 JavaScript 的继承机制,我们再来看一下 JavaScript 中的一些内置构造器。

常见的有:

  • Object
  • Number
  • Boolean
  • String
  • Array
  • RegExp
  • Date
  • Function
  • Error

另外还有 MathJSON 等内置对象。

其中 MathJSON 本身就是对象,并不是通过 new 来创建实例的构造器。

例如 var mm=new Math(1234565); 这种写法就是错误的。

这时候又会产生一个问题。

我们平时定义字符串、数字、对象的时候,并没有总是使用 new,例如:

var str="This is a String";

或者:

var book= {
name: "Javascript",
page: 168
};

为什么这样也可以?

这里其实涉及 JavaScript 中的原始值、对象以及包装对象等机制。由于和今天要讲的问题关系不大,这里暂时不展开。

那么哪些对象具有 prototype 属性?

这里需要特别注意:

prototype 是函数对象上的属性,用于原型继承和构造实例。

例如:

function Human(){
}

alert(Human.prototype);
可以访问到 Human.prototype
但是:
var he=new Human();

alert(he.prototype);
//则是 undefined

//类似地:
var str="I am a String Object";

alert(str.prototype);
//结果同样是 undefined

因为这里的 str 是一个字符串值,并不是构造函数。

所以,理解这个问题最重要的一点就是:

不要把 prototype 理解成“所有 JavaScript 对象都有的属性”。它主要存在于函数对象上,并作为构造函数创建实例时使用的原型对象。

这也就解释了为什么:

Human.prototype 存在,而 he.prototype 不存在。

前面的文章已经提到 he.__proto__ ===Human.prototype

实例对象真正关联的是它的原型,而不是拥有一个自己的 prototype 属性。

评论0

欢迎分享你的看法,也欢迎补充不同的实践经验。