为什么函数不可序列化?

时间:2015-01-13 16:17:15

标签: javascript function serialization meteor argument-passing

背景

Meteor.call()的Meteor文档中,它显示为:

  

如果你包含一个回调函数作为最后一个参数(它不能作为方法的参数,因为函数不可序列化)......

我之前运行过与Meteor.call('name', function() {console.log('abc');}, function() {})类似的内容,其中function() {console.log('abc');}作为 参数 传入,空function() {}用作异步回调的存根。 它有效。

该声明告诉我,我不应将 任何 函数作为函数的参数传递,或仅适用于回调函数。

问题

在任何一种情况下,为什么该功能不可序列化?我的浅薄理解只是可序列化的对象是一个可以将其转换为位序列(1' s和0' s)的对象,并且因为一切数字是比特序列,我不明白为什么函数不可序列化。

我发现了一些explanations,但它们都与Java有关,对于那些还不了解序列化重要性的人来说,它没什么帮助。

为什么函数不可序列化?(以及它与Meteor.call()的关系如何?)

4 个答案:

答案 0 :(得分:7)

在大多数情况下,可序列化意味着您可以将某些内容转换为与语言无关的表示形式,并在其他位置重建原始状态。例如。数组[0,1,2]可以序列化为JSON "[0,1,2]"并在其他地方反序列化。

  

在任何一种情况下,为什么该函数不可序列化?

一个函数对象(在JS中)由两部分组成:它的主体(代码)和它所定义的环境。每个函数都是一个闭包。获取函数的来源很简单,但是无法获得其环境状态。

示例:

var foo = 42;
function bar() {
    console.log(foo);
}

thirdService(bar);

thirdService不知道定义函数的环境。它所能做的就是获取函数体的字符串表示,但它不知道foo的值

答案 1 :(得分:2)

该声明的Meteor文档意味着API(Meteor.call)可以告诉您将回调作为最后一个参数传递,因为它知道函数的参数不能是要传递给服务器的参数之一,因为它们必须可序列化为JSON。

所以:当你使用Meteor.call()来调用方法时,第一个参数是要调用的方法的名称。然后将零个或多个参数传递给方法,并且每个参数必须可表示为JSON。最后,如果你想要一个异步回调,你将它作为最后一个参数传递。

Meteor.apply()形成对比,后者执行相同的操作,但需要三个参数:方法名称,参数值数组和(可选)回调。因为所有方法参数都在数组中,所以不需要做任何“嗅探”来判断是否存在回调参数。

答案 2 :(得分:1)

我认为这归结为事物序列化的格式。通常使用我遇到的每个例子都使用JSON来序列化Javascript对象,而简单地说JSON不支持function数据类型。

如果查看json.org,您可以看到支持数据类型。您可以在同一站点中看到下图中支持的不同值:

enter image description here

最接近函数的是将它表示为一个字符串,但是在反序列化过程中没有什么可以告诉你如何将它重新补充回Javascript函数。

答案 3 :(得分:1)

以下列对象为例

var aFancyValue = 123;
var obj = {
   propName: "A value"
   funcName: function(){
      // you do something fancy with aFancyName variable
   }
}

现在,当您尝试序列化obj时,如果函数是可序列化的,那么aFancyValue应该有一些其他方式可以使函数无法正常工作。

其他内容如属性是文字,他们不依赖于其他任何东西。它们本身是完整的,但可能的函数可能与它们不同,因为它们可能依赖于数据,这些数据在序列化时可能无法访问。

简而言之,环境,功能的上下文未知,这就是他们无法序列化的原因。

相关问题