这可能是个愚蠢的问题。我用谷歌搜索但找不到答案。如下所示,变量声明不允许作为函数的参数。
function t(a) {
alert(a);
}
t(var x = 1); // Uncaught SyntaxError: Unexpected token var
t(let x = 1); // Uncaught SyntaxError: missing ) after argument list
t(x = 1); // working fine and later I am able to access x also
console.log(x); // printing 1
但是函数声明被允许作为函数的参数,如下所示。
function callback(str, f1, f2) {
if(str == "")
f1();
else
f2();
};
callback("", function b1() { alert("empty") }, function b2() { alert("not empty") }); // working fine
b1(); // Throwing error Uncaught ReferenceError: b1 is not defined
谁能帮我理解一下
最佳答案
好问题!我会把它分成几部分。此处将有很多 Material 可供谷歌搜索,因为您的问题涉及多个深层次主题。
声明是声明。它们没有值(value),因此不能作为参数。这段代码...
let a = 1
...没有值(value),意味着这些都不起作用:
doStuff(let a = 1)
let b = (let a = 1)
(let a = 1) + 5
名字a , 或 a + 5 , 或 f(a)是表达式,与语句不同,表达式具有值。但是a的声明本身没有。
请注意,您对此的直觉并不荒谬:在其他语言中,let a = 1是一个计算结果为 1 的表达式.不在 Javascript 中。
但是,function关键字确实有值:Function它定义的对象。与为方便起见的语言构造变量不同,Functions是存在于运行程序中的实际对象。我们说函数是一等对象。
你可以做所有这些:
doStuff(function f() {})
let a = function f() {}
let b = (function f() {}) + 5 // the result of this is funny
回到你的例子,然后:
callback(
"", // a String object
function b1() { alert("empty") }, // a Function object
function b2() { alert("not empty") } // a Function object
);
类似这样:
function b1() { alert("empty") }
function b2() { alert("not empty") }
callback("", b1, b2)
但不完全是。让我们谈谈作用域。
名称(例如变量或函数)的范围是具有该定义的代码部分。
例如:
// Top-level scope:
let a = 1
if (a == 1) {
// Inner block scope:
let b = 2
console.log(a, b) // 1, 2
}
console.log(a, b) // 1, undefined
作用域存在于更大的作用域中。内部作用域可以访问周围的作用域(因此 a 和 b 在 block 内部可见)但反之则不行(因此 b 在外部不可见)。
当您创建 function 时调用中的对象...
f(function a() { })
...它们被困在内部范围内,无法从外部引用。
在您的示例代码中,您注意到声明 a像这样工作:
f(a = 5)
这……很不幸。确实是 Javascript 历史的产物。在现代代码中,您应该始终使用 let或 const定义变量。
那么它为什么有效?两个原因。首先,因为它是一个赋值,而不是一个声明。像这样:
let x = 1
f(x = 2)
赋值是表达式。他们评估分配的值。 x = 2 的值是2 , 和 x作为副作用发生变化。
第二个原因是不幸的。当你避开 let , var或 const关键字,您隐式使用了 global范围。
这是所有作用域之母,可以从代码中的任何位置访问存在于其中的名称。所以,如果你只是这样做......
f(a = 5)
... 没有声明 a当前作用域中的任何地方,它在全局作用域中隐式声明,并且赋值发生。把它想象成这样(伪代码):
global let a
f(a = 5)
那当然不是有效的 Javascript。但是你明白了。
关于javascript - 为什么变量声明不允许作为参数,而函数声明可以?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54032324/
类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
我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co
我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
为什么4.1%2返回0.0999999999999996?但是4.2%2==0.2。 最佳答案 参见此处:WhatEveryProgrammerShouldKnowAboutFloating-PointArithmetic实数是无限的。计算机使用的位数有限(今天是32位、64位)。因此计算机进行的浮点运算不能代表所有的实数。0.1是这些数字之一。请注意,这不是与Ruby相关的问题,而是与所有编程语言相关的问题,因为它来自计算机表示实数的方式。 关于ruby-为什么4.1%2使用Ruby返
exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby中使用两个参数异步运行exe吗?我已经尝试过ruby命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何rubygems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除
我正在查看instance_variable_set的文档并看到给出的示例代码是这样做的:obj.instance_variable_set(:@instnc_var,"valuefortheinstancevariable")然后允许您在类的任何实例方法中以@instnc_var的形式访问该变量。我想知道为什么在@instnc_var之前需要一个冒号:。冒号有什么作用? 最佳答案 我的第一直觉是告诉你不要使用instance_variable_set除非你真的知道你用它做什么。它本质上是一种元编程工具或绕过实例变量可见性的黑客攻击
我有一些Ruby代码,如下所示:Something.createdo|x|x.foo=barend我想编写一个测试,它使用double代替block参数x,这样我就可以调用:x_double.should_receive(:foo).with("whatever").这可能吗? 最佳答案 specify'something'dox=doublex.should_receive(:foo=).with("whatever")Something.should_receive(:create).and_yield(x)#callthere
我正在编写一个gem,我必须在其中fork两个启动两个webrick服务器的进程。我想通过基类的类方法启动这个服务器,因为应该只有这两个服务器在运行,而不是多个。在运行时,我想调用这两个服务器上的一些方法来更改变量。我的问题是,我无法通过基类的类方法访问fork的实例变量。此外,我不能在我的基类中使用线程,因为在幕后我正在使用另一个不是线程安全的库。所以我必须将每个服务器派生到它自己的进程。我用类变量试过了,比如@@server。但是当我试图通过基类访问这个变量时,它是nil。我读到在Ruby中不可能在分支之间共享类变量,对吗?那么,还有其他解决办法吗?我考虑过使用单例,但我不确定这是
我正在使用active_admin,我在Rails3应用程序的应用程序中有一个目录管理,其中包含模型和页面的声明。时不时地我也有一个类,当那个类有一个常量时,就像这样:classFooBAR="bar"end然后,我在每个必须在我的Rails应用程序中重新加载一些代码的请求中收到此警告:/Users/pupeno/helloworld/app/admin/billing.rb:12:warning:alreadyinitializedconstantBAR知道发生了什么以及如何避免这些警告吗? 最佳答案 在纯Ruby中:classA