I have a file that exports some functions in a Vuejs project, and I need to use them also in an external environment .. inComponent I know which function I should use by identifying by name and comparing with a .JSON file this works cool in the environment of development but when I build the project the functions are renamed as in the image:
Is there any other reference in these functions where I can identify them other than by name? any reference in memory I don't know? Thank you!
You can define a unique value in the body of each function and then when you have a reference to one of the functions in your list you can call the toString() method of the function reference to get the source code of the function - and then check whether the desired unique value is present in the code.
Something like this:
const myFunc1 = function (...)
{
const uniqueIdent = 'zvjbesvfexrxe3cg4g3ewumkaj2hrz9m';
.....
}
const myFunc2 = function (...)
{
const uniqueIdent = 'y4wxfjedrr3mh6k5ju2gcff6wxafjcz5';
.....
}
// make the list of functions globally available
window.myFuncList = { myFunc1, myFunc2 };
// try to find the uglyfied name of Func2
var key;
var realNameFunc2;
for (key in window.myFuncList)
{
if (window.myFuncList[key].toString().indexOf('y4wxfjedrr3mh6k5ju2gcff6wxafjcz5') !== -1)
{
realNameFunc2 = key;
break;
}
}
// you can now invoke your function as realNameFunc2(...)
Related
Hey there StackOverflow people of the world! Thank you for helping me with my question, and I apologize if this question gets a bit long winded. I just want to be clear about all the details and constraints I am working with. I found a few other related questions but nothing that was really very clear about how to get around my specific problem, unless I am missing something. Related questions:[1, 2]
Question Setup:
This is what I have and how it works, my question will be about a problem I am having
I've got a object that I've filled with named functions. The purpose of the object map is to contain many functions calls from multiple files. I am calling each function a "business rule" and they are typically very small functions that do a singular action with well-defined inputs and outputs. It also lets me chain the function calls sequentially with the output from functionCall1 becoming the input functionCall2.
All of my business rule definitions up to this point have been in a set of files that reside in a sub-folder called "Framework", but what I am trying to do now is allow the "Client" to define their own business rules in their own files and their own object map of function calls. What I would like to do is add all of the function calls to a single shared data storage.
What I am trying to avoid doing:
I am NOT trying to serialize the function calls, neither am I trying to leverage the 'eval' capability of JS. I've tried working with this before and it gets really messy!
Also I DO NOT want to declare a "class" object or use the "this" keyword for this reason:
10-most-common-javascript-mistakes
What is working:
(NOTE: Greatly simplified as I currently have hundreds of "business rules")
// rulesLibrary.js
import * as stringParsing from './Rules/stringParsing';
export const rulesLibrary = {
['Echo']: (inputData, inputMetaData) => (inputData, inputMetaData),
// Business Rules
// ********************************
// StringParsing rules in order
// ********************************
['stringToBoolean']: (inputData, inputMetaData) => stringParsing.stringToBoolean(inputData, inputMetaData),
['stringToDataType']: (inputData, inputMetaData) => stringParsing.stringToDataType(inputData, inputMetaData),
}
// stringParsing.js
export const stringToBoolean = function(inputData, inputMetaData) {
var returnData;
// Function Body...
return returnData;
};
export const stringToDataType = function(inputData, inputMetaData) {
var returnData;
// Function Body...
return returnData;
};
// ruleBroker.js
import * as rules from './rulesLibrary';
export const processRules = function(inputData, inputMetaData, rulesToExecute) {
var returnData = inputData;
for (var rule in rulesToExecute) {
if (rulesToExecute.hasOwnProperty(rule)) {
var key = rule;
var value = rulesToExecute[key];
returnData = rules.rulesLibrary[value](returnData, inputMetaData);
}
}
return returnData;
};
You can see in the code above the rulesLibrary is defining the functions in an object rulesLibrary = {}; which is also exported. Then in the ruleBroker we are calling the associated function:
rules.rulesLibrary[value](returnData, inputMetaData)....and this works great.
My Goal
My goal is to rather than store all these functionName: functionCall on the rules.rulesLibrary, I want to store them on a singleton data storage object I am calling "D".
Here is the definition of "D":
// data.js
export var data = {};
What I have tried - Attempt 1
I first tried to assign all of the contents of the rules.rulesLibrary from the rulesLibrary.js directly to "D" like so in the ruleBroker.js file:
// NOTE: I am actually doing this inside a function so I can boot-strap the rules.rulesLibrary into `D`, before the application begins going about the business of calling business rules via the ruleBroker.
import * as rules from './rulesLibrary';
var D = require('../Resources/data');
D['BusinessRules'] = {};
D['BusinessRules'] = rules.rulesLibrary;
This did not work and attempting to console.log(JSON.stringify(D)); just gave me back:
D{BusinessRules} = {};
What I have tried -- Attempt 2
So I thought maybe I should try and define the business rules map named function calls directly on "D" like so in the rulesLibrary.js file:
// NOTE: I am again doing all of this inside a boot-strap function for the same reason as above.
export const initRulesLibrary = function() {
D['BusinessRules'] = {};
D['BusinessRules'] = {
['Echo']: (inputData, inputMetaData) => (inputData, inputMetaData),
// Business Rules
// ********************************
// StringParsing rules in order
// ********************************
['stringToBoolean']: (inputData, inputMetaData) => stringParsing.stringToBoolean(inputData, inputMetaData),
['stringToDataType']: (inputData, inputMetaData) => stringParsing.stringToDataType(inputData, inputMetaData),
}
};
Again I get the same thing, contents of D are: D{BusinessRules} = {}.
Maybe console.log in combination with JSON.stringify doesn't work with function-objects?
But then again, I do have rules that return a function-object and I have been able to stringify those function-objects in the past with this same code. Granted it's a function-object so I am not expecting it to look pretty when stringified, but that's not the point. The point should be that the function-object exists on 'D' and it clearly does not, what am I missing here? How can I get all my function-objects mapped on 'D' so that I can add/merge more function-object definitions to it?
Ultimately this is what I want to be able to do:
function addClientRules(clientRules) {
Object.assign(D['BusinessRules'], clientRules['BusinessRules']);
};
Such that D now contains all of the system-defined business rules & all of the client defined business rules. Then in the ruleBroker, I would just call whatever business rule like this:
export const processRules = function(inputData, inputMetaData, rulesToExecute) {
var returnData = inputData;
for (var rule in rulesToExecute) {
if (rulesToExecute.hasOwnProperty(rule)) {
var key = rule;
var value = rulesToExecute[key];
// OLD WAY:
// returnData = rules.rulesLibrary[value](returnData, inputMetaData);
// NEW WAY:
returnData = D['BusinessRules'][value](returnData, inputMetaData);
}
}
return returnData;
};
Any ideas? Thoughts? Edits? Rants? Am I at least on the right track?
Thank you again for your help! Hopefully this will help someone else too!! :-D
Turns out I was already doing everything correctly to begin with. It's just that console.log & JSON.stringify don't work well with a object map of functions.
The function maps do contain the function calls, just don't expect your console.log even with JSON.stringify to dump that data in any way. You have to proceed with making the call as if it is there and verify that the execution is successful by putting console logs in the function that calls the rule and additionally putting console logs in the rule that is to be executed.
It does work and it's pretty cool when it does!!
I hope this can help someone else, please comment if you have any additional questions and/or if I can provide additional solution details.
Log of successful execution:
c.ccustomEcho resolves as: customEcho
BEGIN warden.executeBusinessRule function
businessRule is: customEcho
ruleInput is: Calling Custom Echo from application
ruleMetaData is: Calling Custom Echo from application
BEGIN ruleBroker.processRules function
inputData is: "Calling Custom Echo from application"
inputMetaData is: "something-nothing"
rulesToExecute are: {"0":"customEcho"}
BEGIN clientStringParsing.customEcho function
inputData is: Calling Custom Echo from application
inputMetaData is: something-nothing
returnData is: Calling Custom Echo from application clientStringParsing.customEcho
END clientStringParsing.customEcho function
returnData is: "Calling Custom Echo from application clientStringParsing.customEcho"
END ruleBroker.processRules function
returnData is: Calling Custom Echo from application clientStringParsing.customEcho
END warden.executeBusinessRule function
Cheers
~Seth
I'm using gulp-uglify ~1.5.4 for my javascript minification, in a file a have this code : columns[j].colDef.cellRenderer.name === 'dateRenderer', cellRenderer is a function so cellRenderer.name will return he name of that function.
So when the function is dateRenderer() that code should return true which doesn't happens since after the minification the function got mangled.
I found this thread : Make gulp-uglify not mangle only one variable but I don't want to tell uglify what variables to mangle and not, isn't there any other way to solve this ? like in AngularJS we are using the $inject service.
If you don't want to specify to uglifyjs what function names should it skip from mangling, store that function's name as a string.
function dateRenderer() {
// do something useful
}
dateRenderer.rendererName = 'dateRenderer'
// later ...
var fn = dateRenderer
if (fn.rendererName === 'dateRenderer') {
console.log('ok!')
}
...or set its name after you called that specific function:
function dateRenderer() {
dateRenderer.rendererName = 'dateRenderer'
// do something useful
}
// later ...
var fn = dateRenderer
// do something
dateRenderer()
if (fn.rendererName === 'dateRenderer') {
console.log('ok!')
}
I am trying to create a webpack plugin, that will parse the code for a certain function and replace it with another function, that plugin will also expose the new function as a global.
class someName {
constructor(local, domain, translationFile, options) {
}
apply(compiler) {
// exposing ngt function as a global
compiler.plugin('make', function(compilation, callback) {
var childCompiler = compilation.createChildCompiler('someNameExpose');
childCompiler.apply(new webpack.DefinePlugin({
ngt: function(singular , plural, quantity) {
return quantity == 1 ? singular : plural;
}
}));
childCompiler.runAsChild(callback);
});
// searching for the getValue function
compiler.parser.plugin(`call getValue`, function someNameHandler(expr) {
// create a function to replace getValue with
let results = 'ngt('+ expr.arguments +')';
const dep = new ConstDependency(results, expr.range);
dep.loc = expr.loc;
this.state.current.addDependency(dep);
return true;
});
}
}
module.exports = someName;
update / rephrase
I have an issue here, when compiler.parser.plugin('call getValue', function someNameHandler(expr) {...} block is commented the ngt function exist as a global.
when its not commented, i get an error, ngt is undefined.
commented i mean /**/
I found a workaround for that but its far then idea. right now what I do is I export an anonymous function that does what i want.
You can see the plugin here:
Github
You can override the method based on environment. Let's say you have a method
function a(){
//original defination
}
Now based on the environment, if it's a production you could do something like this
if (environment.production) {
function a(){
//overridden defination
}
}
You can use the webpack-merge plugin, it's very useful to do exactly what do you want.
https://github.com/survivejs/webpack-merge
First approach using module.export without creating object
File:AuthFilter.js
function callbackAuthService() {
....AUTH SERVICE CALLBACK CODE....
}
module.exports = {
checkAuthentication: function() {
.....HTTP REQ TO AUTH SERVICE......
}
File app.js(using checkAuthentication)
var authFilter = require('./filters/AuthFilter');
/* Before Filter */
app.all('*', authFilter.checkAuthentication);
Second approach using prototype by creating object
File:AuthFilter.js
var authFilter = function()
{
function callbackAuthService() {
....AUTH SERVICE CALLBACK CODE....
}
this.checkAuthentication=function() {
.....HTTP REQ TO AUTH SERVICE......
}
}
module.exports = authFilter;
File app.js(using checkAuthentication)
var authFilter = require('./filters/AuthFilter');
var authFilterObj=new(authFilter);
/* Before Filter */
app.all('*', authFilterObj.checkAuthentication);
Which way is better ?
as far as i know in node js functions are object so in first way we are exporting function object and calling it (it is not static function call).
Please correct if i am wrong (please consider design style and performance in mind).
Also while using lib like sha1,mongo,redis,sql,request i observed that i don't have to create the object and the use their functions(means they are using first approach)
I am trying to build a lib and I need to call functions dynamically depending on the variables I have in parameter like this
strategies = min
function dispatchRuleToStrategy(strategies)
{
$.each(strategies, function(index, value) {
strategy = "strategy_" + value;
});
}
function strategy_min()
{
// do something
}
How can I call the function strategy_min() from dispatchRuleToStrategy()?
I've been trying a couple of things none of which are working.
Thanks for your help
Use an Object to create a dictionary of your functions e.g. lib
var lib = {
'strategy_min': strategy_min
};
then you can invoke via the key in this dictionary Object
lib['strategy_min']();
If you've named all your functions and you don't want to re-type the names over and over, you could
var lib = {};
function addToLib(fn) {
lib[fn.name] = fn;
}
// then
addToLib(strategy_min);
// or
[strategy_min].forEach(addToLib);
Put them in an object and use the property name:
var strategy_table = {
min: function() {
// do something
},
max: function() {
// do something else
},
...
};
Then you can access them as strategy_table[value]:
$.each(strategies, function(index, value) {
strategy_table[value]();
});
Others have already suggested to create a wrapper object for the functions, however, if your strategy_min() function is in the global scope, you can access it directly:
window['strategy_' + value]();
window in browsers refers to the global object. The bracket notation is used to access properties whose keys are dynamically generated. This way you are accessing the function, which is a property of the global object, i.e. window, and calling it using the parentheses.
Finally I found the real problem. I was in a jquery document ready which is a closure. I did not knew what closures were before today.
Thanks all for your help
You can use eval() function in the following manner
$.each(strategies, function(index, value) {
strategy = "strategy_" + value;
eval(strategy+"()");
});