为什么函数不可序列化?
Why is a function not serializable?
背景
在 Meteor.call()
的 Meteor 文档中,它显示:
If you include a callback function as the last argument (which can't be an argument to the method, since functions aren't serializable)...
我之前有 运行 类似于 Meteor.call('name', function() {console.log('abc');}, function() {})
的内容,其中 function() {console.log('abc');}
作为 参数传入 ,空 function() {}
用作异步回调的存根。 而且有效。
那句话告诉我我不应该将 任何 函数作为参数传递给函数,或者只适用于回调函数。
问题
在这两种情况下,为什么该函数不可序列化?我的浅薄理解只是,可序列化对象是一个可以将其转换为位序列(1
和 0
的对象),并且由于 everything 数字是位序列,我不明白为什么函数不可序列化。
我找到了一些explanations,但它们都与Java有关,对于还不知道连载意义的人来说,帮助不大。
为什么函数不可序列化?(它与 Meteor.call()
有什么关系?)
我相信这归结为序列化的格式。一般来说,我遇到的几乎每个例子都使用 JSON 来序列化 Javascript 对象,然后简单地把 JSON 不支持 function
数据类型。
如果您查看 json.org,您可以看到支持的数据类型。您可以在取自同一站点的下图中看到支持的不同值:
最接近函数的方法是将其表示为字符串,但在反序列化过程中,没有任何信息可告知您如何 re-hydrate 返回 Javascript 函数。
在大多数情况下,可序列化意味着您可以将某些内容转换为与语言无关的表示形式,并在其他地方重建原始状态。例如。数组 [0,1,2]
可以序列化为 JSON "[0,1,2]"
并在其他地方反序列化。
In either case, why is that function not serializable?
一个函数对象(在 JS 中)由两部分组成:它的主体(代码)和它定义的环境。每个函数都是一个闭包。获取函数的源代码很容易,但你无法获取其环境的状态。
示例:
var foo = 42;
function bar() {
console.log(foo);
}
thirdService(bar);
thirdService
不知道函数定义的环境。它所能做的就是获取函数体的字符串表示,但它不知道 [=14 的值=].
以下面的对象为例
var aFancyValue = 123;
var obj = {
propName: "A value"
funcName: function(){
// you do something fancy with aFancyName variable
}
}
现在,当您尝试序列化 obj
时,如果函数是可序列化的,那么 aFancyValue
应该以某种方式存在,否则函数将无法工作。
属性等其他内容都是文字,它们不依赖于任何其他内容。它们本身是完整的,但函数 可能 不是那样,因为它们可能取决于数据,在序列化时可能无法访问这些数据。
简而言之,函数的环境,上下文是未知的,这就是它们无法序列化的原因。
Meteor 文档中该语句的意思是 API (Meteor.call
) 可以告诉您将回调作为最后一个参数传递,因为它知道参数是一个函数不能 是要传递给服务器的参数之一,因为这些参数必须可序列化为 JSON。
所以:当你使用Meteor.call()
调用方法时,第一个参数是要调用的方法的名称。然后传入零个或多个参数以传递给该方法,并且每个参数都必须表示为 JSON。最后,如果你想要一个异步回调,你将它作为最后一个参数传递。
将其与 Meteor.apply()
进行对比,后者做同样的事情,但采用 三个 参数:方法名称、参数值数组和(可选)回调.因为所有的方法参数都在数组中,所以不需要做任何"sniffing"来决定是否有回调参数。
背景
在 Meteor.call()
的 Meteor 文档中,它显示:
If you include a callback function as the last argument (which can't be an argument to the method, since functions aren't serializable)...
我之前有 运行 类似于 Meteor.call('name', function() {console.log('abc');}, function() {})
的内容,其中 function() {console.log('abc');}
作为 参数传入 ,空 function() {}
用作异步回调的存根。 而且有效。
那句话告诉我我不应该将 任何 函数作为参数传递给函数,或者只适用于回调函数。
问题
在这两种情况下,为什么该函数不可序列化?我的浅薄理解只是,可序列化对象是一个可以将其转换为位序列(1
和 0
的对象),并且由于 everything 数字是位序列,我不明白为什么函数不可序列化。
我找到了一些explanations,但它们都与Java有关,对于还不知道连载意义的人来说,帮助不大。
为什么函数不可序列化?(它与 Meteor.call()
有什么关系?)
我相信这归结为序列化的格式。一般来说,我遇到的几乎每个例子都使用 JSON 来序列化 Javascript 对象,然后简单地把 JSON 不支持 function
数据类型。
如果您查看 json.org,您可以看到支持的数据类型。您可以在取自同一站点的下图中看到支持的不同值:
最接近函数的方法是将其表示为字符串,但在反序列化过程中,没有任何信息可告知您如何 re-hydrate 返回 Javascript 函数。
在大多数情况下,可序列化意味着您可以将某些内容转换为与语言无关的表示形式,并在其他地方重建原始状态。例如。数组 [0,1,2]
可以序列化为 JSON "[0,1,2]"
并在其他地方反序列化。
In either case, why is that function not serializable?
一个函数对象(在 JS 中)由两部分组成:它的主体(代码)和它定义的环境。每个函数都是一个闭包。获取函数的源代码很容易,但你无法获取其环境的状态。
示例:
var foo = 42;
function bar() {
console.log(foo);
}
thirdService(bar);
thirdService
不知道函数定义的环境。它所能做的就是获取函数体的字符串表示,但它不知道 [=14 的值=].
以下面的对象为例
var aFancyValue = 123;
var obj = {
propName: "A value"
funcName: function(){
// you do something fancy with aFancyName variable
}
}
现在,当您尝试序列化 obj
时,如果函数是可序列化的,那么 aFancyValue
应该以某种方式存在,否则函数将无法工作。
属性等其他内容都是文字,它们不依赖于任何其他内容。它们本身是完整的,但函数 可能 不是那样,因为它们可能取决于数据,在序列化时可能无法访问这些数据。
简而言之,函数的环境,上下文是未知的,这就是它们无法序列化的原因。
Meteor 文档中该语句的意思是 API (Meteor.call
) 可以告诉您将回调作为最后一个参数传递,因为它知道参数是一个函数不能 是要传递给服务器的参数之一,因为这些参数必须可序列化为 JSON。
所以:当你使用Meteor.call()
调用方法时,第一个参数是要调用的方法的名称。然后传入零个或多个参数以传递给该方法,并且每个参数都必须表示为 JSON。最后,如果你想要一个异步回调,你将它作为最后一个参数传递。
将其与 Meteor.apply()
进行对比,后者做同样的事情,但采用 三个 参数:方法名称、参数值数组和(可选)回调.因为所有的方法参数都在数组中,所以不需要做任何"sniffing"来决定是否有回调参数。