Let's say I have the following JavaScript
function myGlobalFunction(){
function firstInnerFunction(){
return "rainbows";
}
function secondInnerFunction(){
function innerInnerFunction(){
return "clouds";
}
return innerInnerFunction();
}
return firstInnerFunction(); //valid call
}
Is there anyway I can call firstInnerFunction() in the global scope? If so(and better yet), can I go two levels down and call innerInnerFunction() from the global scope?
What are you trying to achieve in doing something like that? I would suggest something like the following:
var myGlobalFunction = {
var innerInnerFunction() { return "clouds"; }
get firstInnerFunction() { return "rainbows"; }
get secondInnerFunction() { return innerInnerFunction(); }
};
You can then call firstInnerFunction() with something like this:
myGlobalFunction.firstInnerFunction;
as for calling innerInnerFunction() from the global scope, myGlobalFunction.secondInnerFunction() will serve the same purpose as calling innerInnerFunction() directly.
In short, no. JavaScript is function scoped, so everything inside is hidden from the outside. So in order to access the inner functions you'll need to expose them somehow.
Absolute simplest (but ugly) option is to do something like this:
var secondInnerCopy;
function myGlobalFunction(){
function firstInnerFunction(){
return "rainbows";
}
function secondInnerFunction(){
function innerInnerFunction(){
return "clouds";
}
return innerInnerFunction();
}
secondInnerCopy = secondInnerFunction;
return firstInnerFunction(); //valid call
}
myGlobalFunction();
secondInnerCopy(); //valid (only after myGlobalFunction called though)
Better option would be to restructure into an object graph with functions:
var global = {
myGlobalFunction: function(){
return this.inner.firstInnerFunction(); //valid call
},
inner: {
firstInnerFunction: function() {
return "rainbows";
},
secondInnerFunction: function(){
return this.inner.innerInnerFunction();
},
inner: {
innerInnerFunction: function(){
return "clouds";
}
}
}
};
global.myGlobalFunction();
global.inner.inner.innerInnerFunction();
//etc...
I don't think that this is possible, however I could be wrong. You could do something like this to access the nested functions via the top level function.
function A(x) {
function B(y) {
function C(z) {
alert(x + y + z);
}
C(3);
}
B(2);
}
A(1); // alerts 6 (1 + 2 + 3)
Another Example
function addSquares(a,b) {
function square(x) {
return x * x;
}
return square(a) + square(b);
}
a = addSquares(2,3); // returns 13
b = addSquares(3,4); // returns 25
c = addSquares(4,5); // returns 41
Check this link, it has some good information on functions and nested functions in Javascript. Javascript Function Scope
I believe something like this would also work, though I like what Alconja did.
var myGlobalFunction = {
firstInnerFunction: function(){
return "rainbows";
},
secondInnerFunction : function(){
var innerInnerFunction = function(){
return "clouds";
}
var inninnerFuncTwo = function(){
return 'more stuff';
}
return {
inn : innerInnerFunction,
inn2: inninnerFuncTwo
}
}
}
myGlobalFunction.secondInnerFunction().inn();
myGlobalFunction.secondInnerFunction().inn2();
If you want a call to globalFunction to define firstInnerFunction, you can do that as follows
function globalFunction() {
firstInnerFunction = function() { return "rainbows" ; } ;
}
For innerInner function, you can do as follows
function globalFunction() {
firstInnerFunction = function() { return "rainbows" ; } ;
secondInnerFunction = function() {
innerInnerFunction = function() { return "clouds" ; } ; }
}
Now you can do this
globalFunction() ; // defines firstInnerFunction and secondInnerFunction in the global scope
firstInnerFunction() ; // returns "rainbows"
secondInnerFunction() ; // defines innerInnerFunction
innerInnerFunction() ; // returns "clouds"
Related
I have the following self-invoked function which is being utilized by the other functions across the app:
var Api = (function() {
var requestPayload;
var responsePayload;
return {
getRequestPayload: function() {
return requestPayload;
},
setRequestPayload: function(newPayloadStr) {
requestPayload = JSON.parse(newPayloadStr);
},
getResponsePayload: function() { // <-Function's output I need
return responsePayload;
},
setResponsePayload: function(newPayloadStr) {
responsePayload = JSON.parse(newPayloadStr);
}
};
}());
This function is called by other functions in the app like:
Api.getResponsePayload();
I want to capture the output of getResponsePayload function every time this function is called to utilize is for further processing.
I tried to create another function:
function runMe(responsePayload) {
console.log(responsePayload)
}
And it gets called everytime getResponsePayload function is called but the output I'm getting is undefined:
getResponsePayload: function() {
runMe();
return responsePayload;
How can I get the output of getResponsePayload function everytime it gets called by any other function in the app?
Just shim it, assuming this is for debug purposes. You may want to handle exceptions more explicitly, just be sure to rethrow to be transparent.
Api.getResponsePayload = (function(previousFn){
return function() {
var result = previousFn.apply(this, arguments);
// print them or something
return result;
}
})(Api.getResponsePayload)
Edit: Here is a generalisation of the method above:
function logMethodCallsOn(object, methodName) {
var actualMethod = object[methodName];
object[methodName] = function() {
var title = methodName + "(" + Array.prototype.map.call(arguments, function (val) { return JSON.stringify(val); }).join(", ") + ")";
try {
var result = actualMethod.apply(this, arguments);
console.log(title + " =", result);
return result;
} catch (e) {
console.error(title + " threw", e);
throw(e);
}
}
}
logMethodCallsOn(Api, 'getResponsePayload');
logMethodCallsOn(Api, 'setResponsePayload');
You could use callbacks. I'm not sure if you whant a callback in the get or the set, this example shows both.
Eric's answer is more elegant and can be used even if Api is an external object. But I think this simpler implementation could be useful for learning purpose.
var Api = (function(getResponsePayloadCallback, setResponsePayloadCallback) {
var requestPayload;
var responsePayload;
return {
getRequestPayload: function() {
return requestPayload;
},
setRequestPayload: function(newPayloadStr) {
requestPayload = JSON.parse(newPayloadStr);
},
getResponsePayload: function() { // <-Function's output I need
getResponsePayloadCallback(responsePayload);
return responsePayload;
},
setResponsePayload: function(newPayloadStr) {
responsePayload = JSON.parse(newPayloadStr);
setResponsePayloadCallback(responsePayload);
}
};
})(getResponsePayloadHandler, setResponsePayloadHandler);
Api.setResponsePayload('{ "foo": "foo value" }');
var requestPayload = Api.getResponsePayload();
function getResponsePayloadHandler(value) {
console.log("getResponsePayload: " + value.foo);
}
function setResponsePayloadHandler(value) {
console.log("setResponsePayload: " + value.foo);
}
You are not passing any parameter to runMe so it logs undefined. Change your getResponsePayload function to:
getResponsePayload: function() {
runMe(responsePayload);
return responsePayload;
}
Anyway be aware that if you don't set responsePayload, you console output will still be undefined cause responsePayload is only declared but never assigned a value (so it will have undefined value)
I'm using the revealing module pattern somewhat like this:
var SomeClosure = function () {
var SomeInnerVar = 4;
function InnerGetTheVar() {
return SomeInnerVar;
}
function InitClosure() {
// there's something else happening here that requires me to
// wait for document.ready before initializing the closure
setInterval(IncreaseSomeInnerVar, 10000);
}
function IncreaseSomeInnerVar() {
SomeInnerVar = SomeInnerVar + 1;
}
InitClosure();
return {
GetTheVar: InnerGetTheVar
}
}
$(document).ready(function () {
SomeClosure = SomeClosure();
});
Now why is it that if in the console I type this:
SomeClosure.GetTheVar = 2;
SomeClosure.GetTheVar; // outputs 2!
Why doesn't the closure keep SomeInnerVar protected? I don't want the outer scope to be able to change SomeInnerVar like that.
Thanks for your suggestions.
Actually, SomeInnerVar is still 'protected', in this sense. However, you are overwriting SomeClosure's GetTheVar attribute with the value 2, which isn't 'protected' in the same sense. In other words, you aren't modifying SomeInnerVar, you're modifying GetTheVar.
Instead of just returning an object literal, use Object.defineProperty:
var out = {};
if ( Object.defineProperty ) {
Object.defineProperty(out, 'GetTheVar', {
value: InnerGetTheVar,
writable: false
});
} else {
out.GetTheVar = InnerGetTheVar;
}
return out;
Sorry if my question wasn't clear enough. I'll put my code here...
var chain = {
'fn_1' : {
//fn_1 code here
chain.fn_2();},
'fn_2' : {
//fn_2 code here
chain.fn_3();}
...and so on
}
Let's say if i wana call chain.fn_1(), is there a way I can do that without calling chain.fn_2()?
What I can think of right now is a flag, but that would be alot of excess flags probably for each function. Do you guys have any ideas?
If the series of functions each call the next one you're correct, you'd need to have some sort of flag. In all likelihood, what would be best would be to modify your functions so that they return the reference to the object. Then you could chain like so:
var chain = {
'fn_1': function () {
// do something here.
return this;
},
'fn_2': function () {
// do something here.
return this;
},
'fn_3': function () {
// do something here.
return this;
}
};
// call the full chain:
chain.fn_1().fn_2().fn_3();
// call only the middle.
chain.fn_2();
g.d.d.c's answer is best, but if you can't modify the object for some reason, you could do this:
var _oldFn2 = chain.fn_2
chain.fn_2 = function() { return; };
chain.fn_1();
chain.fn_2 = _oldFn2;
var chain = {
fn : ['fn1', 'fn2', 'fn3'],
call : function(name) {
var i = 0, pos = -1, l = this.fn.length;
for(i = 0; i < l; i += 1) {
if(this.fn[i] == name) {
pos = i;
}
if(pos !== -1) {
this[this.fn[i]]();
}
}
},
fn1 : function() {
alert('fn1');
},
fn2 : function() {
alert('fn2');
},
};
chain.call('fn1'); //chain
chain.fn1(); //single
I was working on some code earlier today, when I realized, "Hey! This code would be more concise and semantic if I abstracted the idea of a boolean not out of an anonymous function and into a prototype function..."
Consider a predicate generator:
function equalTo(n) {
return function(x) {
return n==x;
};
}
So you can use it like so:
[1,2,3,4,1,2,3,4].filter(equalTo(2)) == [2,2]
Now, my idea is to make a predicate "inverser":
Function.prototype.not = function() {
//???
}
So that you can say:
[1,2,3,4,1,2,3,4].filter(equalTo(2).not) == [1,3,4,1,3,4]
My first stab at the implementation was probably very naive:
Function.prototype.not = function () {
return ! this(arguments);
}
And probably why it didn't work.
How would you implement this function, and why?
I'm just trying to wrap my head around functional ideas, and know JavaScript well enough to know it can be used to do this, but just not how.
Your implementation won't work for several reasons:
You need to return a function, not a boolean.
You should pass the arguments as-is, not wrapped in an array.
You should preserve the context (this keyword) that the function would have been called in.
I would implement it like this:
Function.prototype.not = function (context) {
var func = this;
return function() { return !func.apply(context || this, arguments); };
}
I return an anonymous function (function() { ... })
I call apply to call the original function in the current contexts with the actual arguments.
(EDIT) Free bonus: I added an optional context parameter which will override this for the callback.
I would probably do it like so (but perhaps with some sort of namespacing):
function not (x) {
return !x;
}
function id (x) {
return x;
}
function compose (/*funcs*/) {
var args = arguments.length
? Array.prototype.slice.call (arguments)
: [id]
;
return function () {
var val = args [args.length - 1].apply (null, arguments);
for (var i = args.length - 2; i >= 0; --i) {
val = args [i] (val);
}
return val;
};
}
[1,2,3,4,1,2,3,4].filter (compose (not, equalTo (2)));
Using your idea:
function equalTo(n) {
var fn = function(x) {
return n == x;
};
fn.not = function(x) {
return n != x; // use this for simpler conditions
return !fn.apply(this, arguments); // use this for more complex logic
}
return fn;
}
So your example would work:
[1,2,3,4,1,2,3,4].filter(equalTo(2).not) == [1,3,4,1,3,4]
Edit: You can write a helper function (better name to be found) so not doesn't need to be redefined every time:
function generateFnWithNot(fn) {
return function () {
var f = fn.apply(this, arguments);
f.not = function () {
return !f.apply(this, arguments);
}
return f;
};
}
So when you're defining your functions, you can define them as normal with the exception of wrapping a generateFnWithNot call:
var equalTo = generateFnWithNot(function (n) {
return function (x) {
return n == x;
};
});
equalTo(5) // resolves to function () { return n == 5; }
equalTo(5).not // resolves to function () { return n != 5; }
I'm writing a global error handling "module" for one of my applications.
One of the features I want to have is to be able to easily wrap a function with a try{} catch{} block, so that all calls to that function will automatically have the error handling code that'll call my global logging method. (To avoid polluting the code everywhere with try/catch blocks).
This is, however, slightly beyond my understanding of the low-level functioning of JavaScript, the .call and .apply methods, and the this keyword.
I wrote this code, based on Prototype's Function.wrap method:
Object.extend(Function.prototype, {
TryCatchWrap: function() {
var __method = this;
return function() {
try { __method.apply(this, arguments) } catch(ex) { ErrorHandler.Exception(ex); }
}
}
});
Which is used like this:
function DoSomething(a, b, c, d) {
document.write(a + b + c)
alert(1/e);
}
var fn2 = DoSomething.TryCatchWrap();
fn2(1, 2, 3, 4);
That code works perfectly. It prints out 6, and then calls my global error handler.
My question is: will this break something when the function I'm wrapping is within an object, and it uses the "this" operator? I'm slightly worried since I'm calling .apply, passing something there, I'm afraid this may break something.
Personally instead of polluting builtin objects I would go with a decorator technique:
var makeSafe = function(fn){
return function(){
try{
return fn.apply(this, arguments);
}catch(ex){
ErrorHandler.Exception(ex);
}
};
};
You can use it like that:
function fnOriginal(a){
console.log(1/a);
};
var fn2 = makeSafe(fnOriginal);
fn2(1);
fn2(0);
fn2("abracadabra!");
var obj = {
method1: function(x){ /* do something */ },
method2: function(x){ /* do something */ }
};
obj.safeMethod1 = makeSafe(obj.method1);
obj.method1(42); // the original method
obj.safeMethod1(42); // the "safe" method
// let's override a method completely
obj.method2 = makeSafe(obj.method2);
But if you do feel like modifying prototypes, you can write it like that:
Function.prototype.TryCatchWrap = function(){
var fn = this; // because we call it on the function itself
// let's copy the rest from makeSafe()
return function(){
try{
return fn.apply(this, arguments);
}catch(ex){
ErrorHandler.Exception(ex);
}
};
};
Obvious improvement will be to parameterize makeSafe() so you can specify what function to call in the catch block.
2017 answer: just use ES6. Given the following demo function:
function doThing(){
console.log(...arguments)
}
You can make your own wrapper function without needing external libraries:
function wrap(someFunction){
function wrappedFunction(){
var newArguments = [...arguments]
newArguments.push('SECRET EXTRA ARG ADDED BY WRAPPER!')
console.log(`You're about to run a function with these arguments: \n ${newArguments}`)
return someFunction(...newArguments)
}
return wrappedFunction
}
In use:
doThing('one', 'two', 'three')
Works as normal.
But using the new wrapped function:
const wrappedDoThing = wrap(doThing)
wrappedDoThing('one', 'two', 'three')
Returns:
one two three SECRET EXTRA ARG ADDED BY WRAPPER!
2016 answer: use the wrap module:
In the example below I'm wrapping process.exit(), but this works happily with any other function (including browser JS too).
var wrap = require('lodash.wrap');
var log = console.log.bind(console)
var RESTART_FLUSH_DELAY = 3 * 1000
process.exit = wrap(process.exit, function(originalFunction) {
log('Waiting', RESTART_FLUSH_DELAY, 'for buffers to flush before restarting')
setTimeout(originalFunction, RESTART_FLUSH_DELAY)
});
process.exit(1);
Object.extend(Function.prototype, {
Object.extend in the Google Chrome Console gives me 'undefined'
Well here's some working example:
Boolean.prototype.XOR =
// ^- Note that it's a captial 'B' and so
// you'll work on the Class and not the >b<oolean object
function( bool2 ) {
var bool1 = this.valueOf();
// 'this' refers to the actual object - and not to 'XOR'
return (bool1 == true && bool2 == false)
|| (bool1 == false && bool2 == true);
}
alert ( "true.XOR( false ) => " true.XOR( false ) );
so instead of
Object.extend(Function.prototype, {...})
Do it like:
Function.prototype.extend = {}
Function wrapping in good old fashion:
//Our function
function myFunction() {
//For example we do this:
document.getElementById('demo').innerHTML = Date();
return;
}
//Our wrapper - middleware
function wrapper(fn) {
try {
return function(){
console.info('We add something else', Date());
return fn();
}
}
catch (error) {
console.info('The error: ', error);
}
}
//We use wrapper - middleware
myFunction = wrapper(myFunction);
The same in ES6 style:
//Our function
let myFunction = () => {
//For example we do this:
document.getElementById('demo').innerHTML = Date();
return;
}
//Our wrapper - middleware
const wrapper = func => {
try {
return () => {
console.info('We add something else', Date());
return func();
}
}
catch (error) {
console.info('The error: ', error);
}
}
//We use wrapper - middleware
myFunction = wrapper(myFunction);
Here is an ES6 style:
const fnOriginal = (a, b, c, d) => {
console.log(a);
console.log(b);
console.log(c);
console.log(d);
return 'Return value from fnOriginal';
};
const wrapperFunction = fn => {
return function () {
try {
const returnValuFromOriginal = fn.apply(this, arguments);
console.log('Adding a new line from Wrapper :', returnValuFromOriginal);
} catch (ex) {
ErrorHandler.Exception(ex);
}
};
};
const fnWrapped = wrapperFunction(fnOriginal);
fnWrapped(1, 2, 3, 4);
The following wrapping utility takes a function and enables the developer to inject a code or wrap the original:
function wrap(originalFunction, { inject, wrapper } = {}) {
const wrapperFn = function(...args) {
if (typeof inject === 'function') {
inject(originalFunction, this);
}
if (typeof wrapper === 'function') {
return wrapper(originalFunction, this, args);
}
return originalFunction.apply(this, args);
};
// copy the original function's props onto the wrapper
for(const prop in originalFunction) {
if (originalFunction.hasOwnProperty(prop)) {
wrapperFn[prop] = originalFunction[prop];
}
}
return wrapperFn;
}
Usage example:
// create window.a()
(function() {
const txt = 'correctly'; // outer scope variable
window.a = function a(someText) { // our target
if (someText === "isn't") {
throw('omg');
}
return ['a', someText, window.a.c, txt].join(' ');
};
window.a.c = 'called'; // a.c property example
})();
const originalFunc = window.a;
console.log(originalFunc('is')); // logs "a is called correctly"
window.a = wrap(originalFunc);
console.log(a('is')); // logs "a is called correctly"
window.a = wrap(originalFunc, { inject(func, thisArg) { console.log('injected function'); }});
console.log(a('is')); // logs "injected function\na is called correctly"
window.a = wrap(originalFunc, { wrapper(func, thisArg, args) { console.log(`doing something else instead of ${func.name}(${args.join(', ')})`); }});
console.log(a('is')); // logs "doing something else instead of a(is)"
window.a = wrap(originalFunc, {
wrapper(func, thisArg, args) {
try {
return func.apply(thisArg, args);
} catch(err) {
console.error('got an exception');
}
}
});
a("isn't"); // error message: "got an exception"
The last example demonstrates how to wrap your function with a try-catch clause
As far as polluting the namespaces, I'm actually going to pollute them some more...
Since everything that happens in JS is initiated by an event of some kind, I'm planning to call my magical wrapper function from within the Prototype Event.observe() method, so I don't need to call it everywhere.
I do see the downsides of all this, of course, but this particular project is heavily tied to Prototype anyway, and I do want to have this error handler code be as global as possible, so it's not a big deal.
Thanks for your answer!