我从Functional Programming with JavaScript Using EcmaScript 6书中获取了此代码。
这就是代码的工作原理。由于内部变量doPayment()
在第一次运行中设置为() => { say("Payment Done") }
,因此多次调用done
不会执行输入箭头函数true
。
但我的理解是,每次调用doPayment()
时,每次都会使用done
初始化变量false
,因此内部箭头函数每次都会运行。
它是如何运作的?
function say(v)
{
document.querySelector('#out').innerHTML += v + "</br>";
}
const once = fn => {
let done = false;
return function() {
return done ? undefined : ((done = true), fn.apply(this, arguments));
}
}
var doPayment = once(() => {
say("Payment Done");
});
doPayment();
doPayment();
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<span id="out" style="font-family: roboto"></span>
</body>
</html>
---------更新--------------------
看到像这样一个中等复杂的问题被要求关闭是如此令人沮丧,因为它与其他问题重复。
在所有答案中,@西尔维斯特的答案被选为正确的答案。我也给出了自己的解释作为答案。
答案 0 :(得分:2)
但我的理解是,每次调用doPayment()时,每次都会使用false初始化变量
行#Creating sampleobject
$o = "Update Result",
" Message: The update completed successfully, but the system needs to be rebooted for the changes to be effective.",
" Reboot Required: true",
" VIBs Installed: VMware_bootbank....................."
$upgradecomm = New-Object psobject -Property @{
Host = "Server1"
Output = $o
}
#Verify that sampleobject is correct
$upgradecomm | Format-List *
#Output
Host : Server1
Output : {Update Result, Message: The update completed successfully, but the system needs to be rebooted for the changes to be effe
ctive., Reboot Required: true, VIBs Installed: VMware_bootbank.....................}
#Check if successfull and rebooted are in the message-string in output
if($upgradecomm.Output -match 'Message: .*?successfull.*?rebooted') { "Do something" }
#Output
Do something
位于let done = false
的正文中,因此在调用once
时执行。 once
的正文仅为doPayment
,因此当您致电return done ? undefined : ((done = true), fn.apply(this, arguments));
时,这是唯一执行的内容。
答案 1 :(得分:2)
当您致电once
时,本地变量done
初始化为false
,并返回功能。该函数是绑定到doPayment
的函数,因此每次调用都会检查并可能改变在创建该函数的done
调用中创建的once
。
如果你要做两个:
const fnPrint = console.log.bind(null, "test");
const fn1 = once(fnPrint);
const fn2 = once(fnPrint);
此处fn1
和fn2
来自once
的两个不同调用,因此他们的闭包中会有不同的 done
绑定。
fn1() ; prints "test"
fn1() ; does nothing
fn2() ; prints "test"
fn2() ; does nothing
答案 2 :(得分:1)
你的一次函数由两个函数组成,第一个函数返回第二个函数。
当您最初使用应该只运行一次的回调函数调用它时,将执行第一个函数。发生这种情况时,您将done
值设置为false
并返回第二个函数。
现在当你调用原始函数时,你不再直接执行它,而是调用从一次返回的函数(第二个函数)。
您正在寻找分配给done
的变量。范围中没有名称的变量,因此解释器将查找父范围,这是第一个可以找到它可以在第二个函数中使用的变量的函数。
return done ? undefined : ((done = true), fn.apply(null, arguments))
上面的说法是,如果done
变量 truthy 返回undefined
,则将done变量设置为true,然后使用给定的函数调用trim函数背景和论点。
了解更多闭包和词汇范围
答案 3 :(得分:-1)
There is a few JavaScript language features in this example. They are (1) closure (2) comma operator (3) high order functions.
The method say
is for just display purpose only, so don't have to considered as part of the problem. once
is a constant function when executed will return another function. The doPayment
is the high order function.
The ((done = true), fn.apply(this, arguments));
uses a comma separated operator. The first expression done = true
is executed first and then the second fn.appy
is executed next and return the results from the second function.
When the JavaScript execution engine runs the first doPayment()
, it runs the following:
var doPayment = once(() => {
say("Payment Done");
});
It runs the once
method. At that time done = false
is executed. Then the inner function is returned and that is assigned to the variable doPayment
. The inner function is:
done ? undefined : ((done = true), fn.apply(this, arguments));
Since the above is inside the once
function, it has created a closure with the variable done
.
Now when the doPayment
(second last statement) is run , so a check is done against done
which evaluates to false
. The expression ((done = true), fn.apply(this, arguments))
gets executed. This will set the done
to true
and executes fn.apply
.
Now when the doPayment
is called again (the last statement), the inner function
done ? undefined : ((done = true), fn.apply(this, arguments));
gets executed. This inner function has already a closure which has done
set to true
already by the previous execution. So it returns undefined
.
When the above code is run, the following functions are run:
once
(after the run, done
is false)done ? undefined : ((done = true), fn.apply(this, arguments));
(after the run, done
is true)done ? undefined : ((done = true), fn.apply(this, arguments));
(after the run done
stays as true