JavaScript:函数为何可拥有属性?exports作为函数添加属性的原理
为什么JavaScript中函数类型的
exports可以添加属性? 这是我遇到的一个代码片段,当obj.exports被赋值为函数类型后,我仍然可以给它添加hello属性,这让我有点困惑,因为通常我们都是给对象类型的exports添加属性。
代码片段:
const obj = { exports: {} } obj.exports = () => { console.log('invoked') } obj.exports.hello = () => { console.log('hello() invoked') } var output = `type of obj => ${typeof obj} #### type of obj.exports => ${typeof obj.exports} #### obj.exports.hello() is ${typeof obj.exports.hello} `; console.log(output);
输出结果:
type of obj => object #### type of obj.exports => function #### obj.exports.hello() is function
我的疑问是:通常exports为object类型时,添加属性很合理,但为什么当exports本身是function类型时,还能拥有属性呢?
嘿,这个问题问得特别好!核心原因其实是在JavaScript里,函数本质上是一种特殊的对象——准确来说是Function对象的实例。
你应该听过JavaScript里"函数是一等公民"的说法,这意味着函数不仅能像普通函数那样被调用,还能完全像对象一样拥有自己的属性和方法。这是因为函数在底层继承自Object,天然具备对象的所有特性:可以添加/删除属性、可以作为参数传递、也能被赋值给变量。
回到你的代码里拆解一下:
- 一开始
obj.exports是个空对象,后来你把它重新赋值成了一个箭头函数() => { console.log('invoked') }。 - 当你执行
obj.exports.hello = ...时,你其实是在给这个函数对象添加一个名为hello的属性,操作逻辑和给普通对象加属性完全一致。 - 这时候
obj.exports本身还是个可调用的函数(所以typeof返回function),但它同时拥有了hello这个函数属性——你完全可以分开调用它们:obj.exports()会执行原函数,打印invokedobj.exports.hello()会执行你添加的属性函数,打印hello() invoked
这种特性在JavaScript里其实很常见,比如你可能见过给函数添加静态属性的场景:
function MyTool() {} MyTool.version = "1.0.0"; console.log(MyTool.version); // 输出 "1.0.0"
这和你代码里给obj.exports添加hello属性是同一个逻辑。
总结一下:函数在JavaScript中既是可执行的函数体,也是一个标准对象,所以你可以给它添加任意属性,这完全符合语言的设计逻辑~
内容的提问来源于stack exchange,提问作者Amirhosein Al
相关产品推荐
相关产品推荐

