js 什么情况下函数的prototype是undefined

Object.prototype.toString.prototype为什么是undefined

Object.prototype.toString是Function类型,那为什么没有原型,怎么做到没有原型的

日常思考

 Object.prototype.toString.prototype  //undefined

疑问

所有函数都有prototype,但为什么例子中的是undefined呢?而且undefined也不是对象

你不知道的javascript上有这么一句话:所有函数默认拥有一个名为prototype的公有并且不可枚举的属性。
所以我很好奇,并且例如Math.max也没有prototype属性

阅读 6.8k
5 个回答
所有函数默认拥有一个名为prototype的公有并且不可枚举的属性

这句话不能说错,只能算话没说完。“默认”确实是这样,但 prototype 只是一个普通属性,可人为设定,__proto__ 才是继承的(虽然也可以修改)。

prototype 存在的意义是在 function 作为 constructor 用时(newsuper)能复制到生成对象的 __proto__ 上。对于一些内部方法明确是不会作为 constructor 的,所以没有 prototype 是很合理的(同时也没有 [[Construct]] 内部属性)。

详细阅读参见规范

Built-in functions that are not constructors do not have a prototype property unless otherwise specified in the description of a particular function.

Object对象本身是一个函数对象,因此其有prototype属性,且Object.prototype的值是空对象{}。
另外,通过Object.prototype.__proto__获取Object的原型时,将会得到null,也就是说原型对象{}就是原型链的终点。

所有函数都有prototype ×

在控制台试试,并没有prototype。

clipboard.png

在 JavaScript 里,对象可分为函数对象和普通对象两类。大家经常可以看到以下说法:

函数对象才有 prototype 属性,而普通对象是没有的。

并不是所有的函数对象都有 prototype 属性。

function Foo() {}

typeof Foo // "function"
typeof Object.prototype.toString // "function"

Foo.prototype // object
Object.prototype.toString.prototype // undefined
如上示例,函数 Foo 中其本身就有一个不可枚举的 prototype 属性。你可以使用 console.dir(Foo) 看看。

image.png

为什么会这样呢?

当我们访问一个对象的属性时,首先从对象本身上开始查找,找不到的话,再往其原型上一层一层的查找...查找的终点是 Object.prototype(它就是原型链的终点)。若找到则直接返回,停止往上查找。若一直到终点都找不到,则返回 undefined

先了解一下:

Object.prototype.__proto__ // null

Object.prototype.toString.__proto__ === Function.prototype // true
Function.prototype.__proto__ === Object.prototype // true
Object.prototype.__proto__ === null // true,原型链终点

所以查找顺序如下:

Object.prototype.toString.prototype // 找不到
Object.prototype.toString.__proto__.prototype // 也找不到
Object.prototype.toString.__proto__.__proto__.prototype // 也找不到
Object.prototype.toString.__proto__.__proto__.__proto__ // 即 bject.prototype.__proto__ 到终点了,返回 undefined

相当于:

Object.prototype.toString.prototype
Function.prototype.prototype
Object.prototype.prototype
Object.prototype.__proto__ // 到终点了,停止查找,返回 undefined

请注意,图中 [[prototype]] 就是上面代码写的 __proto__ 属性,即对象的原型,而旧版 Chrome 浏览器显示的应该是 __proto__,这个应该是 Chrome 90 以后的效果。

image.png

从图中,你可以看到它本身是没有 prototype 属性的,因此会从其原型上查找。(对比下上面的 Foo 函数的图)

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题