我知道闭包是什么。通过在内部函数(外部函数)中插入内部函数并在外部函数内部返回内部函数,可以使全局变量成为局部变量。
我一直试图深入了解javascript和node.js的工作方式。由于闭包非常重要,并且对我来说很难理解该术语(因为我的母语不是英语),所以我花了很多时间在它上面。所有的文章或网站都一直在用简单的“计数器”功能教授闭包,但是我一直在Node.js中寻找真实的例子。
当我在node.js中研究工作线程时,我遵循了“ webworker-threads” npm软件包网站上的说明,并且我实现了以下错误代码。那让我重新考虑关闭。
const express = require("express");
const app = express();
const Worker = require("webworker-threads").Worker;
app.get("/", (req, res) => {
// let counter = 0; // if i put this here code is not working
const worker = new Worker(function() {
this.onmessage = function() {
let counter = 0;
while (counter < 1000000) {
counter = counter + 1;
}
this.postMessage(counter);
};
});
worker.onmessage = function(result) {
console.log(result);
res.send(result);
};
worker.postMessage();
});
app.get("/fast", (req, res) => {
res.send("this is fast");
});
app.listen(3100, () => {
console.log("listening");
});
由于错误,我将let counter=0
放在了worker函数之外,但是服务器挂起并且无法加载。然后,我将其放在worker函数中尝试不同的方法,并且成功了。
我相信我终于在node.js中看到了一个有关闭包的示例。但是我该怎么形容呢?这是正确的吗?
Worker函数无法访问其闭包。
在此示例中,为什么为什么不允许工作者函数访问其关闭?因为只有一个功能要访问 让counter = 0
答案 0 :(得分:2)
理论上,您可以在任何可以使用类/构造函数的地方使用闭包代替。它们本质上都执行相同的事情:封装数据并维护状态-但通过不同的机制。对象使用上下文维护状态(Java称其为“作用域”,但是因为Java实际上没有真正的作用域),而闭包使用作用域进行维护。
关闭对于替换单方法类(这令人惊讶地有很多用途)特别有用:
让我们看一个简单的文件记录器。 OO实现可以是:
class Logger {
constructor (filename) {
this.logfile = fs.openSync(filename,'a');
this.log.bind(this);
}
log (txt) {
const now = new Date().toISOString();
fs.write(this.logfile, `${now} : ${txt}\n`);
}
}
// usage:
const logger = new Logger('file.log');
logger.log('Hello');
可以使用闭包代替实现相同的逻辑:
function makeLogger (filename) {
const logfile = fs.openSync(filename,'a');
return function (txt) {
const now = new Date().toISOString();
fs.write(logfile, `${now} : ${txt}\n`); // <-- using closure here!
}
}
// usage:
const log = makeLogger('file.log');
log('Hello');
取决于与谁交谈,闭包实现更易于阅读(我是对闭包比对类更满意的人之一)。它不仅更短,而且还包含状态,并且不能从其他代码更改。
由于函数是操作范围的唯一机制,因此您还需要使用闭包来创建范围。这在安全性至关重要的代码中尤其有用,例如与身份验证和金融交易相关的代码,这些代码需要与第三方库进行交互。
Node.js专门使用闭包来实现javascript:文件作用域中不存在的东西。
节点中的模块被加载到IIFE中,从而创建了一个闭包。模块文件中的所有变量对于文件中定义的所有函数(关闭)均可见,而其他模块则不可见(除非声明时未使用var
,let
或const
除外)。 Ryan Dahl不想将Javascript修改为一种语言,而只是在该语言之上添加一个框架以使其在浏览器中有用。幸运的是,JavaScript足够强大(有闭包),这是可能的。
在闭包的大规模使用中,有几个真实的例子:
React.FunctionComponent
是React.js的最新功能,允许用户使用闭包来实现React组件而不是类。这通常可以减少代码行和复杂性(是的,这与前端相关,但是规模非常大)
async.js
经常使用闭包来跟踪异步操作
Express.js
混合了。虽然大多数代码都是面向对象的,但它也使用闭包,尤其是在中间件/路由体系结构中。
答案 1 :(得分:-1)
闭包是函数和在其中声明该函数的词法环境的组合。因此,内部函数即使在外部函数返回后也可以访问外部函数的变量。 现在,当我们进入其应用程序时,我们知道node.js不支持访问说明符,隐式闭包使我们能够做到这一点 下面是相同的示例:
a = (function () {
var privatefunction = function () {
alert('hello');
}
return {
publicfunction : function () {
privatefunction();
}
}
})();