![](/img/trans.png)
[英]How to reuse a function in javascript with different variables
[英]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.