簡體   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