草庐IT

javascript - 是否有将全局变量转换为局部变量的简单方法?

coder 2024-07-26 原文

假设我们有一个如下所示的函数:

const fn = () => x;

此函数应返回 x 的值,其中 x 在全局范围内可用。最初这是 undefined 但如果我们定义 x:

const x = 42;

然后我们可以期望 fn 返回 42

现在假设我们想将 fn 呈现为字符串。在 JavaScript 中,我们有 toString 用于此目的。然而,我们还假设我们希望最终在新的上下文中执行 fn(即使用 eval),因此它使用的任何全局引用都应该在我们调用之前或期间内化toString.

在将fn 转换为字符串时,如何使x 成为局部变量,其值反射(reflect)x 的全局值? 假设我们不知道 x 被命名为 x也就是说我们可以假设变量包含在同一个模块中。

最佳答案

如果您希望在将函数转换为字符串时锁定某些变量,则必须将这些变量与字符串化函数一起传递。

它可以像这样实现(用类型写—— typescript 符号)

const prepareForEval = 
  (fn: Function, variablesToLock: { [varName: string]: any }): string => {
    const stringifiedVariables = Object.keys(variablesToLock)
        .map(varName => `var ${varName}=${JSON.stringify(variablesToLock[varName])};`);

    return stringifiedVariables.join("") + fn.toString();
  }

然后像这样使用它

const stringifiedFunction = prepareForEval(someFunction, { x: x, y: y })

// you can even simplify declaration of object, in ES6 you simply write
const stringifiedFunction = prepareForEval(someFunction, { x, y })
// all variables you write into curly braces will be stringified
// and therefor "locked" in time you call prepareForEval()

任何 eval 都会在执行的地方声明字符串化变量和函数。这可能是个问题,您可能会将某些变量重新声明为新的未知值,您必须知道字符串化函数的名称才能调用它,否则如果您重新声明已声明的 const,它可能会产生错误变量。

为了克服这个问题,您应该将字符串化函数实现为具有自己范围的立即执行的匿名函数,例如

const prepareForEval = 
  (fn: Function, variablesToLock: { [varName: string]: any }): string => {
    const stringifiedVariables = Object.keys(variablesToLock)
        .map(varName => `var ${varName}=${JSON.stringify(variablesToLock[varName])};`);

    return `
      var ${fn.name} = (function() {
        ${stringifiedVariables.join("")}
        return ${fn.toString()};
      )(); 
    `;
  }

此修改将在单独的范围内声明函数和变量,然后将该函数分配给 fn.name 常量。变量不会污染作用域,在您eval 的地方,它只会声明新的fn.name 变量,这个新变量将被设置为反序列化函数。

关于javascript - 是否有将全局变量转换为局部变量的简单方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42168444/

有关javascript - 是否有将全局变量转换为局部变量的简单方法?的更多相关文章

  1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

    我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

  2. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  3. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  4. ruby-on-rails - 在 Rails 中将文件大小字符串转换为等效千字节 - 2

    我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,

  5. ruby - Facter::Util::Uptime:Module 的未定义方法 get_uptime (NoMethodError) - 2

    我正在尝试设置一个puppet节点,但ruby​​gems似乎不正常。如果我通过它自己的二进制文件(/usr/lib/ruby/gems/1.8/gems/facter-1.5.8/bin/facter)在cli上运行facter,它工作正常,但如果我通过由ruby​​gems(/usr/bin/facter)安装的二进制文件,它抛出:/usr/lib/ruby/1.8/facter/uptime.rb:11:undefinedmethod`get_uptime'forFacter::Util::Uptime:Module(NoMethodError)from/usr/lib/ruby

  6. ruby-on-rails - 如何验证 update_all 是否实际在 Rails 中更新 - 2

    给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru

  7. ruby - 使用 ruby​​ 将 HTML 转换为纯文本并维护结构/格式 - 2

    我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h

  8. Ruby 方法() 方法 - 2

    我想了解Ruby方法methods()是如何工作的。我尝试使用“ruby方法”在Google上搜索,但这不是我需要的。我也看过ruby​​-doc.org,但我没有找到这种方法。你能详细解释一下它是如何工作的或者给我一个链接吗?更新我用methods()方法做了实验,得到了这样的结果:'labrat'代码classFirstdeffirst_instance_mymethodenddefself.first_class_mymethodendendclassSecond使用类#returnsavailablemethodslistforclassandancestorsputsSeco

  9. ruby - 将数组的内容转换为 int - 2

    我需要读入一个包含数字列表的文件。此代码读取文件并将其放入二维数组中。现在我需要获取数组中所有数字的平均值,但我需要将数组的内容更改为int。有什么想法可以将to_i方法放在哪里吗?ClassTerraindefinitializefile_name@input=IO.readlines(file_name)#readinfile@size=@input[0].to_i@land=[@size]x=1whilex 最佳答案 只需将数组映射为整数:@land边注如果你想得到一条线的平均值,你可以这样做:values=@input[x]

  10. ruby - 将散列转换为嵌套散列 - 2

    这道题是thisquestion的逆题.给定一个散列,每个键都有一个数组,例如{[:a,:b,:c]=>1,[:a,:b,:d]=>2,[:a,:e]=>3,[:f]=>4,}将其转换为嵌套哈希的最佳方法是什么{:a=>{:b=>{:c=>1,:d=>2},:e=>3,},:f=>4,} 最佳答案 这是一个迭代的解决方案,递归的解决方案留给读者作为练习:defconvert(h={})ret={}h.eachdo|k,v|node=retk[0..-2].each{|x|node[x]||={};node=node[x]}node[

随机推荐