Can't access inner function properly - javascript

Not sure if this is the right title but should be quick help.
Pretty much I keep on getting errors on testing a function because "TypeError: ParseThis.changeIt is not a function". Here's my code. What am I missing that causing this type error? Thanks!
const ParseThis = () => {
const changeIt = string => string;
return { changeIt: changeIt() }
}
Edit: More details!
Thanks for the help again

When you return your object, maybe you wanted to return the function and not the result of the call:
return { changeIt: changeIt };
or this which is more concise:
return { changeIt };
According to how you are using the translate function, I think you should export it this way:
const Translator = {
const translate = string => string;
};
if (module.exports) {
module.exports = Translator;
}
or this way:
const Translator = () => {
const translate = string => string;
return { translate };
}
if (module.exports) {
module.exports = Translator();
}

Return the function instead of calling it.
const ParseThis = () => {
const changeIt = string => string;
return { changeIt };
}
In the original post, changeIt() is a call to changeIt with no first parameter. It returns the value undefined. To return a function instead of calling it, omit the parenthesis.

Let's analyze your code.
Let's start from this:
const changeIt = string => string;
At this point, changeIt is a function that, given a parameter, it returns that a parameter.
Without an arrow function, if we should use the old classic named function, it would be like this:
function changeIt(parameter) {
return parameter;
}
What happens if you call changeIt() with no parameter? In javascript, when you pass no parameters ot a function, it's like you are passing undefined. So the function will return undefined.
Then you have this line:
return { changeIt: changeIt() }
But as we have seen, changeIt() is equal to undefined. So your code is equivalent to:
return { changeIt: undefined }
Which is clearly not a function!
What you probably meant to do, is not returning the result of function invokation, but return the function itself. So, instead that assigning changeIt(), just assign changeIt:
return { changeIt: changeIt }
Notice that you repeated twice the word changeIt, so you can get rid of this repetition and just write:
return { changeIt }

Your function is returning an object, so instead of
ParseThis.changeIt()
You should be doing something like
const a = ParseThis();
a.changeIt('some string');
But, note that even in your example, changeIt in the returning object is not a function.
Probably you are trying this
const ParseThis = () => {
const changeIt = string => string;
return { changeIt: changeIt};
}
Note that I've used { changeIt: changeIt}, setting changeIt to a reference of the inner function changeIt. And you are using { changeIt: changeIt()} setting changeIt to the value returned of the inner function changeIt. Those are two different operations.

The problem is that you are exporting a function, and not the object containing the nop function. You need to add parenthesis to your dummy:
const Translator = () => {
const translate = string => string;
return { translate };
};
if (module.exports) {
module.exports = Translator(); // add parenthesis here
}
Alternatively you could run the function you import, but I suspect that would be different from your real Translator api.

Related

filter and regex issue

I want to filter an array with a function.
if (this.pendingItems.customer?.emailAddresses) {
this.pendingItems.customer.emailAddresses.filter(email => {
isEmailValid(email);
});
}
the function isEmailValid()
export function isEmailValid(s: string): boolean {
const re =
/^[a-z0-9+-][a-z0-9_+-]*(\.[a-z0-9_+-]+)*#([a-z0-9-]+\.)+[a-z0-9-]{2,}$/i;
return re.test(s);
}
return the correct response (true or false) with the emails(test#email.com and test2email) I pass it, but the filter don't work.
You need to modify your expression slightly. The method you pass to the filter function should return true/false but it always returns void (which will be cast to false).
filter(email => isEmailValid(email))
or
filter(isEmailValid)
or
filter(email => { return isEmailValid(email) })
In case you missed it - you forgot to return the result of the isEmailValid ;)
So the solution was:
if (this.pendingItems.customer?.emailAddresses) {
this.pendingItems.customer.emailAddresses = this.pendingItems.customer.emailAddresses.filter(isEmailValid);
}
I forgot to reassign the variable ;p

return function as an object literal

In this exercise I can't figure out why if I return the function I get an error, while if I return the function as a literal object it works
(module.js not works)
module.exports = {eleva : allaSeconda()}
function allaSeconda(){
function calcola(num){
return num*num
}
return calcola
}
(module.js works)
module.exports = {eleva : allaSeconda()}
function allaSeconda(){
function calcola(num){
return num*num
}
return {calcola}
}
(index.js)
const {eleva} = require('./modulo')
console.log(eleva.calcola(9))
Your syntax is a little bit convoluted, you can simply:
// no need for parenthesis in the exports.
// you export a function that elevates
module.exports = {eleva : allaSeconda}
function allaSeconda(num){
return num*num
}
Which could also be done totally inline:
// no need for parenthesis in the exports.
// you export a function that elevates
module.exports = {
eleva: function(num) {
return num * num;
}
}
And you call it simply like so:
const {eleva} = require('./modulo')
console.log(eleva(9))
Please note that your first example works, if you call eleva directly.

understanding the return keyword

I have this:
validateForm = () => {
for (let i = 0; i < formInputs.length; i++) {
const inputName = formInputs[i];
if (!this.state.form[inputName].length) {
return false;
}
}
}
which im refactoring in to this:
validateForm2 = () => {
Object.keys(this.state.form).map(input => {
if(!this.state.form[input].length) {
return false
}
return true;
})
}
the first one works, when i fill in my form and the function returns true, if one is empty it returns false.
however i cant seem to quite understand the return keyword to get the same result.
Object.keys says it returns an array but even if I say return Object.keys... or else {return true} I don't seem to get the same result. what am I misunderstanding about return?
You could use Array#every, which uses the return value for a short circuit and for returning the check of all truthy items.
validateForm2 = () =>
Object.keys(this.state.form).every(input => this.state.form[input].length);
Array#map utilizes the return value as new item for each item of the array for a new array, which is dicarded in the given example.
In the first example you have only one (arrow) function which returns either false or undefined.
In the second example you have outer (arrow) function that never returns anything - undefined to the calling code, and the second function that you pass as a parameter to Array.map method. return statements inside the parameter function are not returning anything from the outer function.
validateForm2 = () => {
var emptyItems = Object.keys(this.state.form).filter(input => {
return !this.state.form[input].length;
});
return emptyItems.length == 0;
}
You could modify your function to do what you want it to do.
validateForm2 = () => {
return Object.keys(this.state.form).every(input => {
return this.state.form[input].length;
})
}
You are checking that every property has a length (true). If one of them doesn't, your function returns false.
I think you can avoid using .map in favor of .every() which iterates over every single element and checks whether it has a length greater than zero.
const validateForm = (form) => Object.values(form).every((field) => field.length);
let semiEmptyForm = {
firstField : "",
secondfield : "notEmpty"
};
let nonEmptyForm = {
firstField : "notEmpty",
secondfield : "notEmpty"
};
console.log(validateForm(semiEmptyForm))
console.log(validateForm(nonEmptyForm))

Is `eval` the only way to create functions with dynamically determined arity in JavaScript?

I'm using a JavaScript spy library,
simple-spy.
I've found out that when spying on a given function,
the resulting spy always has an arity of 0.
This creates a problem with my use of
this currying function.
So I've submitted a pull-request
that adds arity transparency to
the spy library.
The code looks like this:
function spy(fn) {
const inner = (...args) => {
stub.callCount++;
stub.args.push(args);
return fn(...args);
};
// ends up a string like
// 'a,b,c,d'
// depending on the `fn.length`
const stubArgs = Array(fn.length)
.fill(null)
.map((m, i) => String.fromCodePoint(97 + i))
.join();
const stubBody = 'return inner(...arguments);';
// this seems to be the only way
// to create a function with
// programmatically specified arity
const stub = eval(
// the wrapping parens is to
// prevent it from evaluating as
// a function declaration
`(function (${stubArgs}) { ${stubBody} })`
);
stub.reset = () => {
stub.callCount = 0;
stub.args = [];
};
stub.reset();
return stub;
}
exports.spy = spy;
This seems to work.
Is it possible to do this
without the use of eval?
Is it possible to
reduce the use of eval
to even less that this?
I'm aware that there are other issues
with this spy implementation.
It is simplistic and it works
for my use case so far.
Like Benjamin wrote, I used a simple:
function spy(fn) {
const stub = (...args) => {
stub.callCount++;
stub.args.push(args);
return fn(...args);
};
stub.reset = () => {
stub.callCount = 0;
stub.args = [];
};
stub.reset();
Object.defineProperty(stub, 'length', {value: fn.length});
return stub;
}
exports.spy = spy;
Much, much better looking.

How to properly return an empty function?

I'm using a run-time assignment of functions to account for browser differences. However for un-supported browsers, I want to return an empty function so that a JavaScript error is not thrown.
But, jslint complains about empty functions. What is the jslint happy way to do this?
Empty block.
$R.functionNull = function () {
// events not supported;
};
$R.Constructor.prototype.createEvent = (function () {
if (doc.createEvent) {
return function (type) {
var event = doc.createEvent("HTMLEvents");
event.initEvent(type, true, false);
$NS.eachKey(this, function (val) {
val.dispatchEvent(event);
});
};
}
if (doc.createEventObject) {
return function (type) {
var event = doc.createEventObject();
event.eventType = type;
$NS.eachKey(this, function (val) {
val.fireEvent('on' + type, event);
});
};
}
return $R.functionNull;
}());
You can add a body to your function and have it return undefined:
$R.functionNull = function() {
// Events not supported.
return undefined;
};
This keeps the same semantics as a "truly empty" function, and should satisfy JSLint.
Use the lambda expression:
$R.functionNull = () => void 0;
For me this works best:
emptyFunction = Function();
console.log(emptyFunction); // logs 'ƒ anonymous() {}'
console.log(emptyFunction()); // logs 'undefined'
It's so short that I wouldn't even assign it to a variable (of course you can also use a constant-like variable "EF" or so, that's even shorter and doesn't need the additioal "()" brackets). Just use "Function()" anywhere you need a truly empty function, that doesn't even have a name, not even when you assign it to a variable, and that's the small behaviour difference between my solution and Frédéric's:
// --- Frédéric ---
emptyFunction = function() {
return undefined;
}
console.log(emptyFunction.name); // logs '"emptyFunction"'
// --- me ---
emptyFunction = Function();
console.log(emptyFunction.name); // logs '""' (or '"anonymous"' in chrome, to be fair)
What about returning
return () => undefined;
instead of
return $R.functionNull;

Categories

Resources