对象如何像Javascript中的函数一样可调用?
所以,只要Javascript中的任何东西实际上是一个对象,那么是什么让对象作为函数运行呢?什么样的内部属性和标签使对象表现为我们可以调用的对象,而不仅仅是使用它来存储值?您不能使对象可调用对象如何像Javascript中的函数一样可调用?,javascript,Javascript,所以,只要Javascript中的任何东西实际上是一个对象,那么是什么让对象作为函数运行呢?什么样的内部属性和标签使对象表现为我们可以调用的对象,而不仅仅是使用它来存储值?您不能使对象可调用 您可以将属性添加到已存在的函数对象中。您仍将保留call()行为,但也可以获取和设置属性。javascript中有不同的原型。例如,对象.原型,函数.原型,数组.原型。javascript基于原型继承。这定义了任何对象的类型 创建函数时,其\uuuu proto\uuuu(也称为“dunder proto”
您可以将属性添加到已存在的
函数
对象中。您仍将保留call()
行为,但也可以获取和设置属性。javascript中有不同的原型。例如,对象.原型
,函数.原型
,数组.原型
。javascript基于原型继承
。这定义了任何对象的类型
创建函数时,其\uuuu proto\uuuu
(也称为“dunder proto”)设置为函数。prototype
。基本上,函数继承自函数.prototype
,后者又继承自对象.prototype
。以下示例取自MDN。(注意-我认为\uuuu proto\uuuu
未标准化。对象。应使用getPrototypeOf
)
MDN对原型继承有很好的解释。欲了解更多信息,请阅读此
所以只要javascript中的任何东西实际上是一个对象
当然,JavaScript中并非所有内容都是对象。例如,字符串、布尔值和数字等基本体不是对象。当访问属性时,JavaScript只是将这些原语包装到对象中
是什么使一个对象作为一个函数运行?内部属性和
标签做这项工作是为了使对象表现为执行代码
而不仅仅是存储变量
关于函数是对象的说法是正确的,但是,与只存储键值对的常规对象不同,函数对象有一个特殊的内部方法,它们实现的方法称为。此调用方法执行与函数对象关联的代码,并在调用函数(func\u name()
)时调用。因此,任何实现内部[[Call]]
方法的对象都是可调用的。您自己无法通过实现此属性使对象可调用,因为它不是ECMAScript语言本身的一部分,而是规范使用的方法名。相反,我们使用函数
关键字进行调用。函数对象在一天结束时仍然是对象,因此您可以为其分配属性,也可以访问先前存在的属性:
函数foo(a){
返回a;
}
foo.bar=“foobar”;
console.log(foo.length);//能够访问预先存在的属性
console.log(foo.bar);//能够访问我们自己的财产
console.log(foo(2));//能够调用(由于[[Call]])
有一个内部属性,[[Call]]]
,它确定调用对象时将执行什么
普通对象没有这个内部属性,所以它们不可调用,也不能被设置为可调用
JS中唯一的可调用项是函数(也是对象)、类(实际上是函数,因此也是对象)和封装可调用项的代理对象
要创建可调用对象,请创建一个函数,并使其具有所需的属性和原型。您可以将一个对象分配给函数以获得可调用函数
var对象={foo:42},
callable=Object.assign(函数(){},对象);
console.log(可调用)
console.log(callable())
log(Object.keys(可调用))
能否提供示例代码?只有本机函数和从函数构造函数/类创建的东西是函数。无法将非函数对象转换为函数如果对象实现了内部[[Call]]方法,那么它将是可调用的:这与问题无关。您可以将对象[[Prototype]]
设置为函数。Prototype
但这不会使您的对象神奇地成为可调用对象。例如varo={};setPrototypeOf(o,Function.prototype);console.log(o instanceof函数)
记录为true,但o()
失败。@YuryTarabanko感谢您指出这一点。我刚才回答的是内部属性
,它使对象成为函数
。我认为这是问题的一部分。所以,所有东西最终都继承自对象。prototype
,但函数。prototype
使其成为函数。不是吗?不是真的。这与原型无关。到目前为止,使对象可调用的是内部的[[Call]]
方法,而不是原型。考虑<代码> var o =函数(){控制台.log(“我仍然可调用”)};setPrototypeOf(o,null);console.log(o instanceof函数,Object.getPrototypeOf(o)==null);o()
@YuryTarabanko再次感谢您提供的信息。我尝试了这个let o=function(){};设b={};Object.setPrototypeOf(b,Object.getPrototypeOf(o));b、 _uuuproto_uuuu.call()-->返回未定义的let c={};c、 __proto__.call();-->返回错误
。因此,当您设置原型时,至少会添加原型调用。不确定将对象
转换为可调用函数
是否有意义。所以javascript所做的一切都是正确的。@Aditya我真的不明白你最后对\uuu proto\uuu.call的评论
这有什么好处。
function f() {
return 2;
}
// Functions inherit from Function.prototype
// (which has methods call, bind, etc.)
// f ---> Function.prototype ---> Object.prototype ---> null