简体   繁体   English

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

[英]How to reuse closure with different variables

I want to reuse the function sayMyName but with different variables. 我想重用函数sayMyName,但要使用不同的变量。 Please let me know if I'm structuring this the wrong way and what is the best practice what what I'm trying to do. 请让我知道我是否以错误的方式构造了这种结构,什么是最佳实践?

 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' 

I'm not sure why you specifically want a closure, but by looking at your example it seems that a bind would be more appropriate than a closure. 我不确定您为什么特别想要闭包,但是通过查看您的示例,似乎绑定比闭包更合适。

 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' 

Move your variable myName to the outermost scope: 将变量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' 

Update: Thinking about it, if you're willing to use the non-standard, Error.stack attribute, are willing to use named functions, and are willing to use a naming convention, you could hackishly achieve your goal: 更新:考虑一下,如果您愿意使用非标准的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" 

... and if you're willing to use eval (bad !!!), then you could do fancier things like the following: ...并且如果您愿意使用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" 

You could even use the non-standard, Function.caller attribute, which is probably the cleanest approach (if it works in your browser -- it's non-standard for a reason): 您甚至可以使用非标准的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" 

This is arguably no less code than just passing a parameter, though. 但是,可以说这不仅仅是传递参数。

If you want closure then this is example. 如果您要关闭,那么这是示例。

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