考虑以下类声明:
class A {}
A.prototype.test1 = function test1() { console.log("test1") }
评估test1
的字符串化版本会产生有效的JS,我们可以在这里看到:
const a = new A
eval(`(${a.test1})`)() // outputs "test1"
但是,如果我们以不同但基本相同的方式构建我们的类:
class B {
test2() { console.log("test2") }
}
评估test2
的字符串化版本失败:
const b = new B
eval(`(${b.test2})`)() // SyntaxError: Unexpected token {
(它被字符串化为test2() { console.log("test2") }
,这是无效的JS,除非嵌入在类声明中)
我可以理解字符串化的本机函数不可评估,例如"".indexOf.toString()
将返回包含[native code]
的字符串,我接受了。
但是,有没有办法保证Function.prototype.toString()
调用用户定义的函数(即源代码可用的函数)生成有效的,可评估的JS?
答案 0 :(得分:3)
但是,有没有办法保证
Function.prototype.toString()
调用用户定义的函数(即源代码可用的函数)生成有效的,可评估的JS?
没有。这取决于功能的类型。 The specification requires the following:
toString
陈述要求:
- 字符串表示必须具有 FunctionDeclaration , FunctionExpression , GeneratorDeclaration , GeneratorExpression , AsyncFunctionDeclaration , AsyncFunctionExpression , ClassDeclaration , ClassExpression , ArrowFunction , AsyncArrowFunction 或 MethodDefinition 取决于对象的实际特征。
- 表示字符串中空格,行终止符和分号的使用和放置取决于实现。
- 如果使用ECMAScript代码定义了对象,并且返回的字符串表示形式不是 MethodDefinition 或 GeneratorMethod ,则表示形式必须是如果字符串在词法上下文中使用
eval
进行求值,该词汇上下文等同于用于创建原始对象的词汇上下文,它将生成一个新的功能等效对象。在这种情况下,返回的源代码不得自由提及原始函数源代码未提及的任何变量,即使这些“额外”名称最初在范围内。- 如果实现无法生成满足这些条件的源代码字符串,则必须返回
eval
将引发SyntaxError
异常的字符串。
由于您有 MethodDefinition ,因此您可以获得方法的表示。如果你的函数既不是 MethodDefinition 也不是 GeneratorMethod ,那么你很可能得到一个可以eval
uated(第三点)的表示,但是即使这样,规范也说实现应该返回一个抛出语法错误的表示,所以¯\_(ツ)_/¯
。