Move your variable myName
to the outermost scope:
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:
function sayMyName() {
try {
throw new Error();
}
catch (e) {
if (e.stack) { // non-standard attribute
var reNames = /^\s*at myNameIs([A-Z][^(\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:
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 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.