繁体   English   中英

如何使用不同的变量重用闭包

[英]How to reuse closure with different variables

我想重用函数sayMyName,但要使用不同的变量。 请让我知道我是否以错误的方式构造了这种结构,什么是最佳实践?

 var sayMyName = function(myName) { console.log(myName) }; var name1 = function() { // myName should not be a global variable // because there may be more variables/functions // that I'd want to closed inside sayMyName(). // Declaring all of them to the global scope is not ideal. var myName = 'Walter'; sayMyName(); // I don't want to pass in myName as argument like this: // sayMyName(myName); // I want myName to be implicitly included in sayMyName() // I want to pass in everything that is declared in name1 to sayMyName() implicitly. }; var name2 = function() { var myName = 'White'; sayMyName(); } name1(); // should give me 'Walter' name2(); // should give me 'White' 

我不确定您为什么特别想要闭包,但是通过查看您的示例,似乎绑定比闭包更合适。

 var sayMyName = function(myName) { console.log(myName) }; var name1 = sayMyName.bind(undefined, 'Walter'); var name2 = sayMyName.bind(undefined, 'White'); name1(); // log 'Walter' name2(); // log 'White' 

将变量myName移到最外层范围:

 var myName; var sayMyName = function() { console.log(myName) }; var name1 = function() { myName = 'Walter'; sayMyName(); }; var name2 = function() { myName = 'White'; sayMyName(); } name1(); // should give me 'Walter' name2(); // should give me 'White' 

更新:考虑一下,如果您愿意使用非标准的Error.stack属性,愿意使用命名函数,并且愿意使用命名约定,则可以轻松实现目标:

 function sayMyName() { try { throw new Error(); } catch (e) { if (e.stack) { // non-standard attribute var reNames = /^\\s*at myNameIs([AZ][^(\\s]*)\\s*\\(/mg; reNames.lastIndex = 0; var buffer = []; for (var match = reNames.exec(e.stack); null !== match; match = reNames.exec(e.stack)) { buffer.push(match[1]); } console.log(buffer.join(" ")); } } } function myNameIsWalter() { sayMyName(); } function myNameIsWhite() { myNameIsWalter(); }; myNameIsWalter(); // "Walter" myNameIsWhite(); // "Walter White" 

...并且如果您愿意使用eval (不好!!),那么您可以做一些更奇妙的事情,例如:

 var sayMyName = function () { try { throw new Error(); } catch (e) { if (e.stack) { // non-standard attribute var reNames = /^\\s*at ([_a-zA-Z][_a-zA-Z0-9]+(\\.[_a-zA-Z][_a-zA-Z0-9]+)*)/mg; reNames.lastIndex = 0; var reMyName = /\\bmyName\\s*=\\s*(?:"([^"]*)"|'([^']*)')/g; var identifier, definition, match, myName, buffer = []; while (null !== (match = reNames.exec(e.stack))) { try { identifier = match[1]; if ("sayMyName" !== identifier) { definition = eval(match[1] + '.toString()'); if (/\\bsayMyName\\(\\)/.test(definition)) { reMyName.lastIndex = 0; buffer.length = 0; while (null !== (myName = reMyName.exec(definition))) { buffer.push(myName[1]); } console.log(buffer.join(" ")); } } } catch (_) { // continue } } } } }; function name1() { var myName = "Walter"; sayMyName(); } function name2() { var myName; myName = "Walter"; myName = "White"; sayMyName(); } name1(); // "Walter" name2(); // "Walter White" 

您甚至可以使用非标准的Function.caller属性,这可能是最干净的方法(如果它在您的浏览器中有效-由于某种原因,它是非标准的):

 function sayMyName() { var reMyName = /\\bmyName\\s*=\\s*(?:"([^"]*)"|'([^']*)')/g; var definition, buffer = []; for (var caller = sayMyName.caller; caller; caller = caller.caller) { definition = caller.toString(); if (/\\bsayMyName\\(\\)/.test(definition)) { reMyName.lastIndex = 0; buffer.length = 0; while (null !== (myName = reMyName.exec(definition))) { buffer.push(myName[1]); } console.log(buffer.join(" ")); } } }; function name1() { var myName = "Walter"; sayMyName(); } function name2() { var myName; myName = "Walter"; myName = "White"; sayMyName(); } name1(); // "Walter" name2(); // "Walter White" 

但是,可以说这不仅仅是传递参数。

如果您要关闭,那么这是示例。

function sayMyName(myName){
   return function(){
      console.log(myName); //myName is available from parent scope
      return myName; 
   }
}
var name1 = sayMyName('Walter');
var name2 = sayMyName('White');
//no console output by now
name1(); //Walter
name2(); //White
//myName is not available in global scope
console.log(myName); //undefined 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM