Get caller instance from inside function - javascript

I currently have a few large files that I'd like to break up into smaller ones to ease editing. I feel as though these 'code snippets' wouldn't merit being created as a module and/or would have conflicts with scope if made as such.
So instead I'd perfer to just import the contents from these 'clipped' files, into the current execution scope and then eval them. Figured I'd write a helper function to do this(set in the global scope via the 'main' js file.) but I've ran into a snag.
Is there a way to get the calling instance from within the called function.
What I have so far:
global.acquire = (function() {
var cache = {};
var fileReader = require('fs');
return function (file, updateCache) {
var f = require.resolve(file);
if (f) {
if (cache.hasOwnProperty(f) && !updateCache) {
res = cache[f];
} else {
res = fileReader.readFileSync(f, {encoding: "utf8"});
}
cache[f] = res;
// Is there a way to get the calling function's instance so the eval will execute from the caller's scope?
return eval.apply(caller, '(' + res + ')');
} else {
throw "File not found";
}
}
}());
I know I could either pass the instance, or acquire.apply(), but that feels a bit sloppy if I can retrieve the instance from within the function.

There is no way to get at the caller's scope from within a separate function that is external to that scope without either passing in particular variables or using this to set data you want/need to access.

Related

Access a local variable from a function on the global scope

I have function a JSON/API loading callback function, where my var json = JSON.parse(response); is located that I use to read the JSON data:
// Call JSON File
function loadJSON(callback) {
xobj.overrideMimeType("application/json");
xobj.open('GET', 'pmApp.json', true);
xobj.onreadystatechange = function () {
if (xobj.readyState == 4 && xobj.status == "200") {
// Required use of an anonymous callback as .open will NOT return a value but simply returns undefined in asynchronous mode
callback(xobj.responseText);
}
};
xobj.send(null);
};
// Run loadJSON -
loadJSON(function (response) {
// Parse JSON string into object
var json = JSON.parse(response);
});
The var json is a local variable, and I would like to keep it that way (I don't want to make it global which would fix my issue), but I have a few functions that are called via HTML onChange events or on the global scope that need the json var to function correctly example:
//Global Scope
popBrandFields()
function popBrandFields(){
var brand_items = json.brands[0][client];
};
I cant cal popBrandFields(json) because the var json is not accessible due to being on a local scope. (I want to keep it this way due to security, puting it on the global scope fixes my issue but I want to keep it in the local scope.)
What would be the best way to achieve this?
I was thinking of returning the var json from the function it is defined in but I'm not sure how or if I can even set this type of function to a variable like in the following example:
function f(){
var foo = 100;
return foo;
}
var a = f();
Maybe there is a better way to load the JSON that can achieve what Im looking for if anyone knows of one?
You could ensure that all of the code that needs this value is in a SEF (self executing fuction).
It creates a scope inside the function where you can define all sorts of things, but does not pollute the global scope.
var globalVariable = 'bad'
(function(){
var json = 'not a global variable';
console.log('Your code goes here!');
})();
The solution I found was to create a function that held the rest of my code and vars, then I would call it from the loadJSON function passing in the json var so my new function can access it like so
loadJSON(function (response) {
// Parse JSON string into object
var json = JSON.parse(response);
jsonUsingFunction(json);
});
This way none of my vars are on the global scope.
Also instead of using onChangefrom the HTML I used event listeners which fixed my issue!

what is happening in this code and what will be the basic implementation of the following without the "with" keyword

I was going through a code base that was creating a multi-platform package management and module system for JavaScript.
I found a path of code that was extracting from withing the function that is associated with the "exports" variable.
I have attached the code snippet below, and on running the snippet you will find the "print" object gets extracted from the function.
I want to know two things:-
How is this code working?
can this code be implemented in a more easier way without the with statement?
var context = {
exports: {}
};
var fn = (function(args) {
with(args) {
return function logger() {
exports = {
print: function(res) {
console.log(res);
}
}
}
}
});
fn = fn(context);
fn.call();
context.exports.print('hello World'); //Prints the hello world
First, evaluating a non-string is pointless. Remove the eval call and just use the function.
Technically, the with statement does this:
The with statement adds an object environment record for a
computed object to the lexical environment of the current
execution context. It then executes a statement using this augmented
lexical environment. Finally, it restores the original lexical
environment.
Basically, this means that when you assign an object to the identifier exports, it becomes a property of args.
Don't do this. The with statement has bad performance and is not allowed in strict mode. Just assign the property normally.
var fn = function(args) {
return function logger() {
args.exports = {
print: function(res) {
console.log(res);
}
}
}
};

Is it possible to get the local variable and parameter values with window.onerror

I have a simple javascript error logging mechanism in place and it looks somewhhat like this:
window.onerror = function (ErrorMsg, Url, LineNumber, Col, Error) {
// ajax these to the server, including Error.stack}
The problem is that I'd also like to get the value of the local variables and function parameters when the error occurred. Is this even possible?
I'm thinking about modifying the Function prototype so that each time a function runs, its arguments are stored in a global array of strings and then the error handler would just add this array to the ajax call. Can JavaScript do this?
#1 Can local scope be recovered in onerror() without black magic?
Without this being bound in the scope of window.onerror() or the surrounding variables being directly accessible, it's impossible to regain access to the variables you had set.
What you're mostly wanting access to is this.arguments or arguments or the equivalent, but that's destroyed. Any hope of obtaining a key-value associative array or hash-like object would involve meta-programming ( i.e. reading the function definition to obtain the variable names, and obtaining an exception report to attempt to salvage data ).
See this answer for more on something similar:
Getting All Variables In Scope
But this "lacking functionality" is a good thing:
If you could gain access to what you're asking for, that would likely be a fault in the Javascript engine. Why? Because the variable states and contents themselves are what caused the exception/error, assuming bad code wasn't the issue to begin with.
In other words, if you could get access to a faulty variable, that might be a door into an infinite loop:
Failure due to variable contents.
Error handler triggered.
Trace contents of variable.
Failure due to variable contents.
Error handler triggered.
Trace contents of variable.
Etc.
#2 Can Javascript store all arguments of every function call by voodoo?
Yes. It can. This is probably a really bad idea ( see #1 ) but it is possible. Here is a pointer on where to start:
Is there a way to wrap all JavaScript methods with a function?
From there, what you're wanting to do is push this.arguments or equivalent to a stack of function calls. But again, this is approaching insanity for many reasons. Not the least of which is the need to duplicate all the values, lest you reference mutated variables, or be unable to access the data at all... and like I said above, the problem of bad data in general. But still, it is possible.
Is this even possible?
No. A stack trace is proof that the stack has unwound, all stack frames and all the local variables they contained are gone. As for getting the name of a variable, that is not even possible at run time.
To start off i accept #Tomalak completely.
I was also put in your situation where i needed to debug a remote running app in case of crash.
As a work around I have forked my code for you in a fiddler. Please modify according to your need.
Caveat: You have to wrap the function body with try{..}catch(e){..} as illustrated in the fiddler code.
Please read the inline comments for understanding.
window.onerror = function (errorMsg, url, lineNumber, column, errorObj) {
console.log(errorObj);
}
window.addEventListener("reportOnError", function(e){
console.log(e.detail);
/*Send to the server or any listeners for analysis.*/
//Http.send(e.detail);
});
function ExceptionReport(ex, args, scope) {
var self = {};
self.message = ex.message;
self.stack = ex.stack;
self.name = ex.name;
self.whoCalled = args.callee.caller.name == "" ? "Window": args.callee.caller.name;
self.errorInFunction = args.callee.name;
self.instanceOf = scope.constructor;
self.KeyPairValues = getParamNames(arguments.callee.caller.toString(), Array.prototype.slice.call(args)); //Contains the parameters value set during runtime
window.dispatchEvent(new CustomEvent('reportOnError', {'detail':self}));
}
//Utilties
function getParamNames(fnBody, values) {
var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg,
ARGUMENT_NAMES = /([^\s,]+)/g,
result = fnBody.slice(fnBody.indexOf('(')+1, fnBody.indexOf(')')).match(ARGUMENT_NAMES),
obj={};
fnBody.replace(STRIP_COMMENTS, '');
if(result !== null){
for(var i=0; i < result.length; i++){
obj[result[i]] = values.length !==0 ? values[i] : null;
}
}else{
obj = null;
}
return obj;
}
/*
This is a testing/sample function that throws the error
*/
function testing(a,b,c){
try{
dummy(1,2) ; //This line throws the error as reference error.
}catch(e){
ExceptionReport(e, arguments, this);
}
}
//Class Emulation: For instanceof illustration.
function testingClass(){
this.testing = testing;
}
//Named self executing function: This calls the function
var myvar = (function myvar(){
testing(1,2,3);
})();
//Illustrating instanceof in exception
var myVar2 = new testingClass();
myVar2.testing(1,2,3);
//Calling from global scope this is Window
testing(1,2,3);
//Without variables
testing();
I have used examples to illustrate the behavior of functions called in different circumstances.
Below signifies the varialble used for
self.KeyPairValues : Used to store the function parameter set/passed during runtime
self.errorInFunction : This stores the name of the function error was caused in.
self.whoCalled : This stores the function name that invoked the defective function
self.instanceOf : This stores the name of the instance is called creating a new instance.
Other variables are same as in Error object
The others answers here are spot on, but I might be able to offer a suggestion for a slightly different way to accomplish this. Instead of trying to track all scope in your program, why not add a tagging function that tracks the scope of one function's parameters without affecting the runtime of the function. For for example:
var globalRecord = {};
function record(name, fn) {
return function () {
var args = [].slice.call(arguments);
var record = globalRecord[name] = {
args: args,
arg: {}
};
args.unshift(function (name, value) {
return record[name] = value;
});
fn.apply(args, arguments);
}
}
// Then, you track variables like this
var func = record("func", function (record, a, b, c) {
record("a", a); // named parameters are accessible now
record("b", b); // if some error occurs in the function body
return a + b + c;
});
// Calling func still behaves as before.
func(1, 2, 3);
// Errors handled like this:
window.onerror = function () {
globalRecord.func.args; // ==> last set of arguments past to function
globalRecord.func.arg.a; // specific arguments recorded with names
};
You could even use this method to track scope without using a function by anonymously calling the recorded function.
record("test", function (record) {
var a = record("a", /* whatever */);
var b = record("b", /* ... */ );
// do scope specific stuff that might fail
})();
Of course, this isn't a polished implementation by any stretch, but with a little work, I think you might be able to get the behavior you're looking for without any seriously black magic. By selectively adding and removing record calls as the need presents itself, you can have precise control over what is logged without any intrusive hacks.
You can find your answer in this link.
Before taking bundles from the server, you must modify them. For example, to solve your problem, you can do changes in the mentioned link as follows. In the BuildBundleContent Class make this change:
contents.Insert(blockContentIndex,
string.Format("if(customErrorLogging)customErrorLogging({0}, this){1}",
errVariable, hasContent ? ";" : ""));
If in the modules you have to use something like:
var self = this;
You can use:
contents.Insert(blockContentIndex,
string.Format("if(customErrorLogging)customErrorLogging({0}, self ? self : this){1}",
errVariable, hasContent ? ";" : ""));
And in added js file:
"use strict";
var customErrorLogging = function (ex, module) {
console.log(module);
//do something...
};
I hope help you.

Javascript module pattern scope with this

I was developing using module pattern, and was wondering why I can't acces to the module scope using this. Maybe I'm wrong with the understanding of the revealing module pattern.
Here is the code I use :
var BLOG = window.BLOG || {};
BLOG.Module = (function(){
var
_this = this,
_hasLoaded = false;
function init(){
console.log(_this); // Logs the Window object
}
function _privateMethod(){
$.ajax({
url: 'lazyload/lazyload.html',
success : function( data ){
// _hasLoaded = true; // I want to access the variable in my module, How do I refer to it?
}
});
}
return {
init : init
};
})();
this is determined by how a function is called. If it's called directly, not through an object property (as your outer scoping function is), within that call this will be the global object in loose mode (undefined in strict mode). On browsers, that's the window object.
You wouldn't normally use this to try to refer to things within that outermost scoping function (for this reason).
If something did this:
BLOG.Module.init();
...then within the call to init, this (not _this) would refer to Module and you could refer to other properties on the object you create at the end of your outermost scoping function (there aren't any others currently, just init).
Re your edit:
var
_this = this,
_hasLoaded = false;
// ...
function _privateMethod(){
$.ajax({
url: 'lazyload/lazyload.html',
success : function( data ){
// _hasLoaded = true; // I want to access the variable in my module, How do I refer to it?
}
});
}
Just uncomment that line:
_hasLoaded = true;
This is because both _privateMethod and any ajax success handlers created as a result of calling _privateMethod are closures over the variables defined within your outermost scoping function. So you just refer to them directly.
If this use of the word "closure" is unfamiliar, don't worry, closures are not complicated.
Side note: This is an odd construct:
var BLOG = window.BLOG || {};
...as it mixes code requiring that it be at global scope with code that doesn't require that it be at global scope. It's entirely functional, it's just a bit odd. I'd probably go one way or the other:
// Requires that it's at global scope (and yes, this does work)
var BLOG = BLOG || {};
or
// Creates a global whether it's at global scope or not
window.BLOG = window.BLOG || {};

Avoid conflicts with function naming conventions javascript

I have a bunch of functions in my script which resides in a .js file.
How can avoid conflicts with the names of my functions within the same page if some other script written by some other guys use the same function names as in my script ?
Is there a way to do this?
If you don't need access to those functions outside of your script you can wrap the whole script in an immediately invoked function expression:
(function () {
// Your code here
}());
This introduces a new scope, so any declarations within it are not visible outside of it.
If you do need access outside of that scope, expose your functions as methods of a "namespace":
var YourStuff = (function () {
// Private functions etc...
// Expose public methods
return {
someMethod: function () {}
};
}());
By taking this approach you only introduce a single global identifier, reducing the chances of a conflict. You can call the method as follows:
YourStuff.someMethod();
Use namespaces..
var company = {};
company.doSomething = function() {
};
company.project = {};
company.project.submodule = {};
company.project.submodule.doSomething = function() {};

Categories