I have a function that returns boolean if tree has at least one enebled value:
treeHasEnabledNode(): Function {
let enabled = false;
return function isNodeEnabled(node: T): boolean {
if (!node || !node.children || !node.children.length) return enabled;
if (node.enabled && node.enabled !== undefined) return true;
node.children.forEach((node: T) => {
enabled = isNodeEnabled(node);
});
return enabled;
};
}
Using is:
let hasEnabled = treeHasEnabledNode()(this.tree);
How to return result not calling outher functon (this.tree)?
You can go about this a few ways. The most simple one would probably be to invoke the internal function within the outer function, and return the result:
function treeHasEnabledNode(node) {
let enabled = false;
function isNodeEnabled(node) {
// do whatever. for example:
return enabled
}
return isNodeEnabled(node);
}
const node = {};
console.log(treeHasEnabledNode(node));
However, as #sledetman mentioned in the comments below your question, the code snippet you provided does not "return a boolean if tree has at least one enabled value".
Related
I have one problem statement.
Implement a function propertyExists(obj, path) that takes in an object and a path (string) as arguments and returns ‘False’ if the property doesn’t exist on that object or is null, else returns the value of the property.
And here is solution.
function propertyExists(obj,path) {
// Write logic here
let result = obj.hasOwnProperty(path);
if(result)
{
return (obj.path);
}
else
{
return result;
}
}
Is this correct way of doing it?
Multiple issues:
the first name of the function should represent what it is doing,
Path as variable name is vague but propertyName as a variable is clear.
what you should do is either:
write function called, "getValue" it returns value if exist or null
function getValue(obj,propertyName) {
if(!obj) { // if object not exist
return null;
}
return obj[propertyName];
}
write function called, "propertyExists" should return true if exist else false.
function propertyExists(obj,propertyName) {
if(!obj) { // if object not exist
return false;
}
return obj.hasOwnProperty(propertyName);
}
function propertyExists(obj,path) {
// Write logic here
for(i in path){
if(obj.hasOwnProperty(path[i]) === true){
obj = obj[path[i]];
}else{
return false;
}
}
return obj;
}
object->obj,propertyname->path
function propertyExist(obj, path){
if (obj.hasOwnProperty(path)) return obj[path];
else return false;
};
Here, as far as I can understand, the objects could be nested also.
Let's take obj as {"a":{"b":"dadsa"}} and path as ab
Now, the the solution which you have posted will not work. Ideally, it should return dadsa, but it will return false.
Try the below code, it will work for nested objects also.
function propertyExists(obj,path) {
// Write logic here
var val=obj;
for(a of path){
val=val[a];
if(!val)
return false;
}
return val;
}
function propertyExists(obj,path) {
var val = obj;
for (a of path) {
val = val[a];
if (!val){
return false;
}
return val;
}
I'm creating a function saveOutput that accepts a function, and a string. saveOutput will then return a function that behaves exactly like the passed-in function, except for when the password string is passed in as an argument. When this happens, the returned function will return an object with all previously passed-in arguments as keys, and the corresponding outputs as values.
I think my code below is correct but I run into the Range Error: Maxiumum call stack size exceeded when I run my code.
function saveOutput(inputFunc, string) {
let obj = {};
//inputFunc() accepts one args
//string like a pwd
return function inputFunc(input) {
if (input === string) {
return obj;
} else {
obj[input] = inputFunc(input);
return inputFunc(input);
}
}
//returns a fxn
return inputFunc;
}
//Test cases
const multiplyBy2 = function(num) { return num * 2; };
const multBy2AndLog = saveOutput(multiplyBy2, 'boo');
console.log(multBy2AndLog(2)); // should log: 4
console.log(multBy2AndLog(9)); // should log: 18
console.log(multBy2AndLog('boo')); // should log: { 2: 4, 9: 18 }
You're using the name inputFunc twice. The returned function is called inputFunc so it shadows the callback function passed as parameter. The returned function calls inputFunc which is itself and causes an endless recursion and eventually the "maxiumum call stack size exceeded" error is thrown.
To fix this either use a different name or make it anonymous as the name is not needed anyway, here is the working code with some improvements:
function saveOutput(inputFunc, string) {
let obj = {};
return function (input) { // make it anonymous
if (input === string) {
return obj;
}
// improvement 1: the else block can be omitted here
return obj[input] = inputFunc(input); // improvement 2: no need to call inputFunc twice, just assign and return at the same time
}
// the return statement here is never reached because there is a return right before it so just remove it
}
Read more about variable shadowing here: An example of variable shadowing in javascript
Demo:
function saveOutput(inputFunc, string) {
let obj = {};
return function(input) {
if (input === string) {
return obj;
}
return obj[input] = inputFunc(input);
}
}
const multiplyBy2 = function(num) {
return num * 2;
};
const multBy2AndLog = saveOutput(multiplyBy2, 'boo');
console.log(multBy2AndLog(2));
console.log(multBy2AndLog(9));
console.log(multBy2AndLog('boo'));
I have this method:
wordFormDirty = (): boolean => {
var self = this;
angular.forEach(self.word.wordForms, function (wf, key) {
var wordFormNgForm = 'wordFormNgForm_' + wf.wordFormId
if (!self[wordFormNgForm].$pristine) {
return true;
}
});
return false;
};
From what I see this never returns true. Can someone give me advice as to how I can implement this so that a form that's not pristine will make the wordFormDirty() method return true.
can you try this, in this case, if I've undestand the issue, the first time there is a value true the result is set to true otherwise it remains false
wordFormDirty = (): boolean => {
var self = this;
var result = false;
angular.forEach(self.word.wordForms, function (wf, key) {
var wordFormNgForm = 'wordFormNgForm_' + wf.wordFormId
if (!self[wordFormNgForm].$pristine) {
result = true;
}
});
return result;
};
If you wish to get a result directly from walking the Array, consider using other methods than forEach. E.g.:
return Object.values(this.word.wordForms).some(
({ wordFormId }) => !this[`wordFormNgForm_${wordFormId}`].$pristine
);
I'm asking myself if it's possible to call a function in js, while having additional subfunction inside it
fn(s);
fn.subfn(s);
for example to make utils like this
var s = "123";
string(s) // true
string.blank(s) // false
I think it's possible like this:
function string(s) {
if(s) return typeof(s) === "string";
return {
blank: function(s) {
return s.trim().length === 0;
}
}
}
but every time i call string(s) i'm redefining blank fn, with possible poor performances and poor code, or i'm wrong?
Thanks.
Functions are just objects, so yes, you can just add properties to them:
function string(s) {
return typeof(s) === "string";
}
string.blank = function(s) {
return s.trim().length === 0;
}
This would allow you to make the calls
string(s);
string.blank(s);
just as shown in your example.
Comments to your code:
The function you defined returns an object when you call string, so you would require to call the function as
string().blank(s);
which would be different form the example you showed at the beginning.
You can create a Thing() class and instantiate "thing" objects to prevent redefining functions. (Thing() instead of string() to prevent any sort of collision.)
function Thing(s) {
return {
isString: function() {
return typeof(s) === "string";
},
isBlank: function() {
return s.trim().length === 0;
}
};
}
var t = new Thing("123");
t.isString() // true
t.isBlank() // false
http://jsfiddle.net/KKrsa/
You could try something like this (untested):
function string(s) {
if(s) return typeof(s) === "string";
}
string.blank = function(s) {
return s.trim().length === 0;
}
You might run into issues using "string" for the name of your function, though, because it may clash with the existing String object.
I have a function expression like this :
var inputChecker = function(field) {
return function() {
if(field === '' || field === 'undefined' || field === null) {
return false;
}
return true;
}
}
that I want to use in several different function expressions :
(function($) {
if(inputChecker(x)) {}
})(jQuery);
(function($) {
})(jQuery);
But the problem is inputChecker is not visible in these function expressions when it's declared out of their bodies ? I don't understand why? Isn't inputChecker supposed to be global ?
Dystroy's answer is definitely simpler. But if you want it your way...
The return value of the inputChecker is a function, not boolean. If you want to call the returned function, use () expression:
var fn = inputChecker(x); // gets the function
fn(); // calls the returned function
or shorter
inputChecker(x)();
In your code
(function($) {
if(inputChecker(x)()) {
// custom code here if x is defined
}
})(jQuery);
Note: if you want to check if variable is not undefined, strip the apostrophes - undefined is constant, not string
if(field===undefined)
What you wrote is a function factory. It doesn't return a boolean but a function able to check a property.
This kind of functions is sometimes useful but :
you're here, in the returned function, checking the value of the property received by the factory. As this value can't change (it's embedded in the closure), the produced function holds no more information than just true or false. So it's useless.
you're calling inputChecker(x) as if it was a boolean instead of a function.
So what you probably want is simply
var checkInput = function(field) {
if(field === '' || field === 'undefined' || field === null){
return false;
}
return true;
}
But if you really want to generate different checking functions, dependent on another value, you could use the function factory pattern like this:
var x = true;
var checkInput = (function (x) {
if (x === true) {
return function(field) {
if(field === '' || field === 'undefined' || field === null){
return false;
}
return true;
}
} else {
return function(field) {
//evaluate field differently
}
}
}(x));
Now, dependig on what x is, one or another function will be assigned to checkInput.