assign function to multiple variables without reference - javascript

I'm trying to assign function to multiple variables, the function calls another function getFuncName(), I want getFuncName to return the name of the function that got invoked.
function getFuncName() {
return getFuncName.caller.name;
}
const error = warning = info = verbose = debug = silly = message => {
console.log(getFuncName())
}
When error gets invoked it prints silly, same for warning, info, verbose and debug.
I want that if error gets invoked, it will print error, same for every other variable, Thanks.

The only way you do it is to:
const error = message => {
console.log(getFuncName())
}
const warning = error
const info = error
// etc
On the other hand why would you want to do this? Maybe you wanted to push a log level or something? In this case you could do like this (higher-order functions):
const logger = level => message => {
console.log(level, ': ', getFuncName())
}
const error = logger('error')
// etc

Don't use Function.caller, it's non-standard and does not behave consistently across browsers. It also does not work in strict mode:
'use strict';
function foo () {
function bar () {
console.log(bar.caller.name);
}
return bar();
}
foo();
Just use partial application to create a closure for message => { ... }:
'use strict';
const logger = type => message => {
console.log(type, message);
};
const error = logger('error');
const warning = logger('warning');
const info = logger('info');
const verbose = logger('verbose');
const debug = logger('debug');
const silly = logger('silly');
error('foo');
info('bar');

In your code, besides getFuncName, there is only a single function in existence. It's referred to via 6 different variables, but there is only one function, with one name.
You can't expect the same function to have different names at different times. Anonymous functions can be given a default name by the interpreter when they appear in the code assigned to a variable - in the case that the anonymous function is assigned to multiple variables at once, the rightmost variable name ("silly", in your case) is considered the name of the function.

A one-liner solution from #Patrick Roberts's answer:
const [error, warning, info, verbose, debug, silly] = ['error', 'warning', 'info', 'verbose', 'debug', 'silly'].map(type => msg => {console.log(type, msg);});

Related

How to exclude a custom constructor in webpack treeshaking?

I have the following code in a JS file
(() => {
const Abc = (ab) => {
this.ab = ab;
this.k = () => {
console.log(this.ab);
};
};
window.MySpace = window.MySpace || {};
window.MySpace.abc = new Abc('some var');
})();
I'm using webpack 5 as my bundler. In another file that loads after this constructor, when I tried using window.Myspace.abc.k, it threw an error. With a little investigation, I'm able to understand that the output file does not have the k, as a result of TreeShaking mechanism.
How do I tell webpack to exclude this constructor/method during treeshaking?
window.MySpace.abc = new Abc('some var');
Abc is an arrow function. Arrow functions cannot be used as a constructor, so this line of code is throwing an exception, and thus nothing gets assigned to window.MySpace.abc.
To fix this, use a regular function:
function Abc(ab) {
this.ab = ab;
this.k = () => {
console.log(this.ab);
};
};

If a function is only used in another function should I keep it inside or outside it?

Like in the subject. I have a function like below and I have quite a bit of helping functions declared within a function (twice as much than in the example) because it's the only one using them.
My question is: should I extract those helping functions outside the function to maintain rule "Function should do one job and do it well" or it should be within? I also read about that higher level functions should be higher for better readability, but it somehow doesn't work (shouldn't hoisting make it work?).
const queryThings = async (body = defaultBody) => {
try {
(...)
// helping functions
const isNonTestDeal = obj => (...)
const isNonEmpty = obj => (...)
const replaceHTMLEntity = obj => (...)
const extractCountries = o => (...)
const queried = await query(...) // that one is outside this function
const cases = queriedCases
.filter(isNonTestDeal)
.map(obj => {
let countries = [(...)]
.filter(isNonEmpty)
.map(replaceHTMLEntity)
.map(extractCountries)
let data = {
(...)
}
return data
})
.filter(obj => (...))
.sort((a,b) => a.d - b.d)
.slice(0, 45) // node has problem with sending data of more than 8KB
return cases
} catch (error) {
console.log(error)
}
}
If you declare the function outside, and only use it in one function, then you cause namespace pollution. (What is namespace pollution?) Thus, I would recommend keeping it inside. Also, if you do so, it is easier to read as well, since it will be closer to the code where it is used.
To address your question about hoisting, it only works if you declare your function without assigning it to a variable.
i think when you write function in other function the memory use is better than write out of function
but you can't use in another function it is local function and it isn't public function

How to fix scope problem inside "then" function react?

I am trying to print out of Printer. I am a little new to react and javascript. I am trying to pass the state to a then function of Third Party Code. But i am getting an error:
Cannot read property 'restaurant_name' of undefined
How can i pass state to the scope of then function of qz?
print = () => {
let { state } = this.state;
qz.websocket.connect()
.then(function() {
return qz.printers.find("BillPrinter");
}).then(function(printer) {
var config = qz.configs.create(printer);
var data = [
`${state.restaurant_name}` + '\x0A',
`${state.restaurant_address}`
]
return qz.print(config, data);
});
}
You have some unnecessary destructuring that is causing your error - this.state.state doesn't exist, yet this line:
let { state } = this.state;
Is equivalent to:
let state = this.state.state;
Remove the curly braces and it'll work fine.
let state = this.state;
Also note that state will be a reference to this.state rather than being another object.
Use arrow function to keep the function in the upper scope as #Ali Torki suggested:
.then(printer => {....})

Console integration: get number of errors/warnings thrown?

So if you open up the inspector, you get this (if you're unlucky):
I'm building a tiny JS component which displays debugging information - is there any way to read the number of encountered errors and warnings so far?
A hacky solution I could come up with involves a bit of trickery by replacing the console.(error|log|warn) functions with my own, but I'm yet to test if it works for all cases (e.g. outside of code I own).
Is there a better way to do this?
As noted in this answer, it's generally not a good idea to change the behavior of native objects/methods. However, the following code should get you what you need in a fairly innocuous manner:
// Add this IIFE to your codebase:
(() => {
// Get all of the property names of the console:
const methodsToTrack = Object.keys(window.console);
// Create an object to collect total usage tallies in:
const usageRegistry = {};
for (let i = 0, j = methodsToTrack.length; i < j; i++) {
let methodName = methodsToTrack[i];
// If the property is not a method, don't touch it:
if(typeof window.console[methodName] !== 'function') {
continue;
}
// Cache the original console method here:
let consoleMethod = window.console[methodName];
// Overwrite console's method to increment the counter:
window.console[methodName] = function () {
// Defining registry properties here, so the registry only contains values for methods that were accessed:
usageRegistry[methodName] = usageRegistry[methodName] || 0;
// Execute the original method's behavior, capturing the returned value (if any) in a var, to return it at the end:
const returnedValue = consoleMethod(...arguments);
// Increment the usage registry for the executed method:
usageRegistry[methodName]++;
// Return the value the console's method would have returned, so the new method has the same signature as the old.
return returnedValue;
};
}
// Define a funciton to output the totals to a console log, then clean up after itself:
window.showConsoleTallies = function () {
window.console.log(usageRegistry);
usageRegistry['log']--;
}
})();
// Examples:
showConsoleTallies();
console.log('log 1');
console.error('error 1');
console.log('log 2');
console.warn('warn 1');
console.error('error 2');
console.log('log 3');
showConsoleTallies();
PS: That's the ECMA6 version, but feel free to run it through Babel if you'd like it to be compiled for use in older browsers.

'TypeError: is not a function' in Node.js

I'm getting the error while running the following code in Node.js
var assert = require('assert');
var request = require('request');
var index = require('./index');
it('verify javascript function', function(done) {
var v2 = index.AddNumbers(5, 6);
assert.equal(11, v2);
done();
});
The index.js file contain the following code:
function AddNumbers(a,b){
return a+b;
}
What am I doing wrong?
This happened to me many times because of circular dependency, check if you have 2 classes that are requiring each other, remove one of them from requiring the other and the issue should be solved
With NodeJS modules, to make something public, you have to export it. Add this to the end of index.js:
module.exports.AddNumbers = AddNumbers;
(That's using the old CommonJS modules. For ESM, it would be export AddNumbers;)
Here it is running on my machine:
$ cat index.js
function AddNumbers(a,b){
return a+b;
}
module.exports.AddNumbers = AddNumbers;
$ cat example.js
var index = require('./index');
var v2 = index.AddNumbers(5,6);
console.log(v2);
$ node example.js
11
I'm fairly a beginner at Node JS so I managed to get this error by importing a function like so:
const { functionName } = require('./function')
instead of like so:
const functionName = require('./function')
Editing my post to add an explanation since I've learned more node since I wrote it. If a module exports an object containing multiple functions functions like so:
module.exports = { functionName, otherFunction }
Then the function has to be deconstructed out of the object during the import, as in the first code snippet. If the module exports a single function or a default function, like so:
module.exports = functionName
Then tt must be imported directly, as in the second code snippet.
If you need to expose a specific component, function or a variable to public. You have to exports those components using JavaScript modules.
let add = (a,b)=>{
return ( a+b);
}
module.exports.add=add;
or if you want to expose multiple functions, you can do as follows.
let add = (a,b)=>{
return (a+b);
}
let subtract = (a, b)=>{
return (a-b);
}
module.exports={
add : add,
subtract : subtract
};
This is happening because two files are referencing each other i.e You are calling function (s) from file A in file B and vice versa which is called Circular Dependency.
Your "AddNumbers" function in the "index.js" file should be as follows,
function AddNumbers(a,b){
var addition = function(a, b){
return (a + b) ;
};
module.exports = {
additionResult: addition
};
}
And you need to call it in your "Node.js" file as follows
var assert = require('assert');
var request = require('request');
var index = require('./index');
it('verify javascript function', function(done) {
var v2 = index.additionResult(5, 6);
assert.equal(11, v2);
done();
});
This should work. Please note that you call the function by whatever the token name you exported the return value by (I use a different name here just for clarity). Almost everybody uses the same name as the function name so there are no confusion. Also in ES6, if you use the same name you can export as just,
module.exports = {
addition
};
instead of,
module.exports = {
addition: addition
};
since you use the same name. It is an ES6 feature.
I ran into the same problem while trying to follow a Nodejs tutorial by w3schools.
I copied the following code from them:
exports.myDateTime = function () {
return Date();
};
That, however, wouldn't work for me. What resolved the problem for me was adding module. before the exports keyword like this:
module.exports.myDateTime = function () {
return Date();
};
The most correct answer was from #shimi_tap. I want to reply it as comment, but doesn't have enough reputation, so I am gonna answer it using a simple example, like in this case below:
File A has 3 functions to process database activity: function
addDB, updateDB, and delData;
File B has 2 functions to process User activity on smartphone:
function addHistory, and editHistory;
Function updateDB in file A is calling function editHis in file B, and function editHistory is calling function updateDB in file A. This is what we called circular-dependency. And we need to prevent it by only giving output of state from editHistory and the rest will be processed inside file A.
//ORIGINAL FUNCTIONS which caused CIRCULAR DEPENDENCY
function updateDB() {
//process update function here
//call function in fileB
const history = require("fileB.js");
await history.editHistory(data).then((output) => {
if(output["message"] === "success"){
response = {
state: 1,
message: "success",
};
}
});
return response;
}
//THIS is the WRONG ONE
function editHistory() {
//process function to edit History here
//call function in fileA
const file = require("fileA.js");
await file.updateDB(data).then((output) => { //You should not call it here
if(output["message"] === "success") {
output = {
state: 1,
message: "success",
};
}
});
return output;
}
//==================================================//
//THE FIX
function updateDB() {
//process function here
const history = require("fileB.js");
await history.editHistory(data).then((output) => {
if(output["message"] === "success"){
await updateDB(data).then((output) => {
response = {
state: 1,
message: "success",
};
});
} else {
log("Error");
}
});
return response;
}
function editHistory() {
//process function to edit History here
// No more calling to function inside the file A
output = {
state: 1,
message: "success",
};
return output;
}
https://medium.com/visual-development/how-to-fix-nasty-circular-dependency-issues-once-and-for-all-in-javascript-typescript-a04c987cf0de
this post visualizes the circular dependency injection
like a child or nested file tried to import parent or top-level file
repo.js
service.js
there are 2 files
service.js uses repo.js file by importing
it works
but check in repo.js that it tried to import service.js file
it shows circular dependency injection warning
In my case the problem was the missing semicolon at the end of the lines.
const codec = JSONCodec()
(async () => {
for await (const message of subscription) {
const payload = codec.decode(message.data)
stompServer.send('/topic/update-event', {}, payload)
}
})()
This produced the following error:
TypeError: JSONCodec(...) is not a function
I was so used to writing code without semicolons, which led me to this problem with the bare NodeJs. As soon as I had put the semicolons, the problem disappeared.
A simple way I debugged this (After about 2 days of troubleshooting) was to actually see why 'x' is not a function. Basically, console.log(x) to see the actual object returned. Turned out I was conflicting x with another declared variable (happens especially when you use axios.res and req,res args.
Require the other file in function level.
fileOne.js
function main() {
const fileTwo = require('./fileTwo');
console.log("hello from file one");
}
module.exports = main;
main();
fileTwo.js
function main() {
const fileOne = require('./fileOne');
console.log("hello from file two");
}
module.exports = main;
main();
Now execute > node fileOne.js
Output:
hello from file two
hello from file one
One silly mistake I did was while exporting was:
module.exports = [module_name_1, module_name_2, ..., module_name_n]
The right way is:
module.exports = {module_name_1, module_name_2, ..., module_name_n}

Categories