Javascript — objects containing functions with parameters - javascript

This is a fairly simple question, but I can't seem to find an example online. I've read up on objects and functions (i.e. here), but can't seem to find an example of a function within an object that accepts parameters.
In JavaScript, we can create an object, a nested object, and a method defined by a function:
var testObject = {
nestedObject : {
isNumber : function(number) { return !isNaN(number) };
}
}
How can I call my function with a specific parameter? Is the following correct?
testObject["nestedObject"].isNumber(number)
Thanks!

You kind of have the right idea but you need to refactor your object. This is how it would be written and called.
var testObject = {
nestedObject: {
isNumber :function(number) { return isNaN(number) }
}
}
then
testObject.nestedObject.isNumber(3);

Looks like there were just a few syntax errors in your code. Functions defined within an object behave the same way as regular functions defined outside of an object. The only difference is that you will have to use dot notation to access the functions on objects. So, try this code out:
testObject = {
nestedObject: {
isNumber: function(number) { return !isNaN(number) }
}
}
Now, you can call isNumber like this:
testObject.nestedObject.isNumber(4) // returns true
Note: Assuming you want your function isNumber to return true if the input is a number, we have to negate ( using ! ) the result of isNaN, as it returns true for values that are NaN.
Edit: When accessing properties (functions or otherwise) of an object, you can use dot notation as above, or you could use bracket notation, or some combination of the two. Here are a few examples:
testObject.nestedObject.isNumber(4) // dot notation
testObject['nestedObject']['isNumber'](4) // bracket notation
testObject['nestedObject'].isNumber(4) // combination of both
testObject.nestedObject['isNumber'](4) // alternative combination of both
There is not necessarily a right way to use bracket vs dot notation, but I think dot notation looks a little cleaner. I guess the only advice is to try to be consistent in however you decide to write it.

In this line:
testObject[nestedObject].isNumber(number)
nestedObject will be evaluated and its value will be passed as key of the property of testObject. What you need is to make it literal, to tell JavaScript that that is the property key.
Just to expand the information given by Tyler, these two are equivalents:
testObject["nestedObject"].isNumber(number)
And:
testObject.nestedObject.isNumber(number)

Related

What do the square brackets after ES6 function do?

Recently I was looking for a way to rewrite an ugly switch/case statement and came across this Medium article.
I rewrote my switch/case into an es6 function like this:
const url = category => ({
'itemA': itemAService.getItemCategories(payload),
'itemB': itemBService.getItemCategories(payload),
})[category]
When I call this function with something like const response = url(category); it works, which is great! But then I got to wondering what exactly the [category] means at the end of the function. I thought maybe it was an Immediately Invoked Function, but that didn't seem right either.
The article mentions that it's an object literal, but when I went to the MDN docs I couldn't find anything that explained what this is or what it does, or even any examples that showcase this same thing.
So what does it do?
That shorthand is roughly equivalent to the following traditional function syntax:
function url(category) {
var obj = {
'itemA': itemAService.getItemCategories(payload),
'itemB': itemBService.getItemCategories(payload),
};
return obj[category];
}
It's easier to see what's happening when you create a named variable for the object.
The parentheses are needed around the object in the arrow function because if an arrow function begins with { it's treated as a body containing statements, rather than a value to return.
They could have put [category] immediately after the object literal, rather than after the close parenthesis, that might have been clearer.
It's not "after" the function, it is in the functions body. It could also be written as:
const url = category => {
const obj = {
'itemA': itemAService.getItemCategories(payload),
'itemB': itemBService.getItemCategories(payload),
};
return obj[category];
};
So this is basically just a dynamic property lookup in the object.
What confuses you here are the braces.
Imagine that you have an object expression and you use a property assessor on the variable which points to the object.
obj = {foo: 1, bar: 2}
return obj["foo"]; //returns 1
Now, how would you call a property assessor on an object literal? You need braces around them to complete the shorthand syntax.
return {foo: 1, bar: 2}["foo"]; // WRONG Syntax
return ({foo: 1, bar: 2})["foo"]; // CORRECT syntax
So, your function can be rewritten using the following traditional syntax.
function getUrl(category) {
return ({
'itemA': itemAService.getItemCategories(payload),
'itemB': itemBService.getItemCategories(payload),
})[category]
}

Is there a way to tell whether a function parameter was passed as either a literal or as a variable?

I have a function:
function hello(param){ console.log('param is '+param); }
And two calls. First:
hello(123)
Second:
var a=123; hello(a);
Is there any possible way to tell, from within the hello function, whether param was passed as a var or as a literal value?
NOTICE: I am not trying to solve a problem by this. There are many workarounds of course, I merely wanted to create a nice looking logging function. And also wanted to learn the boundaries of JavaScript. I had this idea, because in JavaScript we have strange and unexpected features, like the ability to obtain function parameter names by calling: function.toString and parsing the text that is returned.
No, primitives like numbers are passed by value in Javascript. The value is copied over for the function, and has no ties to the original.
Edit: How about using an object wrapper to achieve something like this? I'm not sure what you are trying to do exactly.
You could define an array containing objects that you want to keep track of, and check if its in there:
var registry = [] // empty registry
function declareThing(thing){
var arg = { value: thing } // wrap parameter in an object
registry.push(arg) // register object
return arg; //return obj
}
function isRegistered(thingObj){
return (registry.indexOf(thingObj) > -1)
}
var a = declareThing(123);
hello(a);
function hello(param){
console.log(isRegistered(param));
}

Augmenting Types, method not found

I am trying one of the examples from the book 'Java Script the Good Parts'. Find below the code.
It throws an error saying Number has no method integer. Could you please help me understand the problem.
Function.prototype.method = function (name, func) {
this.prototype[name] = func;
return this;
};
Number.method('integer', function () {
return Math[this < 0 ? 'ceiling' : 'floor'](this);
});
After running the above code, it attaches a method integer to Number.prototype
Number.prototype.integer
It displays the function.
Number.integer
It says undefined.
Number.integer(10);
I get - Number() { [native code] } has no method 'integer'
I am not sure where I am going wrong.
I tried by replacing ceiling with ceil. Still it does not work.
You're adding the method to the prototype assigned to Number instances, you're not adding it to the Number function itself.
So to use it, you call the method on an instance of Number, like this: Live Example | Live Source
var n = 3.1415;
var i = n.integer();
console.log("i = " + i); // "i = 3"
Or with a numeric literal: Live Example | Live Source
console.log(3.1415.integer()); // "3"
console.log((3).integer()); // "3"
Note that in the second line above, I had to put the 3 on its own in parens; otherwise, the JavaScript parser thinks the . is a decimal point rather than a property accessor.
Side note: Extending the prototypes of predefined types with enumerable properties can be a bit hazardous. I've never seen any significant problems when people extend Number or String, but there are major problems if you extend Array or Object, so I would stay away from doing that.
Side note 2: In my examples above, I've also corrected the name of Math.ceil (it's ceil, not ceiling).
The method function (which is taken from Javascript the Good Parts) which you are adding to the prototype of Function helps you define a method on given class or type so that all instances or objects of that type inherit that method.
Two problems in your code:
You are calling integer as if it were defined on the class or constructor function Number itself which is not the case, it is defined on the prototype of Number. If the function was actually defined on Number itself, it would have been defined like this:
Number.integer = function() { /* Implementation */ };
You are passing a parameter to the function (i.e. Number.integer(10)), although in the body of the function you aren't dealing with that number, nor you have declared the integer function to accept any parameters. I guess you are confused that this number is being refereed to by the this keyword inside the function but that is not correct.
The method function allows you to define a method on a given type and you can benefit from it like this:
var a = 10.3; // Now a is a Number instance and so it inherits the integer() method
console.log(a.integer()); // call the method on a
You can even call it directly on literals and they will be wrapped automatically by the interpreter, like this:
console.log((32.543).integer());

trying to work dynamically with object properties in javascript

I'm trying to sort out if this is plausible but have gotten syntax errors at best. So I am wondering if it is at all possible.
What I have is an object (example only)
var myObj = {
something1_max:50,
something1_enabled:false,
something1_locked:true,
something2_max:100,
something2_enabled:false,
something2_locked:true,
something3_max:10,
something3_enabled:true,
something3_locked:true
}
and what I want to do through a function is do something like again for example to sum things up..
function displayDetails(theScope, obj)
{
console.log(obj.[theScope]_max);
}
(function(){displayDetails('something3', myObj);})()
so when displayDetails() is called whatever the scope I can see in this example the max for that scope. In the console log for the example I would hope to see 10
Properties of JavaScript objects can always be accessed as a string using the bracket syntax, ie object['property']. This, of course, means you can build that string dynamically:
console.log(obj[theScope + '_max']);
Put the property name string in brackets.
console.log(obj[theScope + '_max']);

constructing javascript variable names at runtime

someFunction(link) {
someOtherFunction('div' + link);
}
By calling someFunction("Test"), the string "divTest" gets passed to someOtherFunction(). But I want the value of the variable "divTest" to be passed.
How can that be done?
Make your variables members of an object. Then you can use [] to access the objects members using a string:
var byname = {
divabc: ...,
divxyz: ...
};
function someFunction(link) {
someOtherFunction(byname['div'+link]);
}
someFunction('abc'); // calls someOtherFunction(byname.divabc)
For this kind of dynamic construction/access of variable names you should use the alternative object notation where:
object.member === object["member"]
This way you could construct your variable name as a string and use it inside square brackets for accessing object members.
eval will do this, but it's usually indicative of some other problem with the program when you want to synthesize identifiers like this. As Ionut says it's better to use the [] notation. I like to link to this whenever questions like this come up.
You should be able to accomplish this with the 'eval' function.
Try this:
var divFoo = "bar";
function someFunction(link) {
someOtherFunction(this['div' + link]);
}
function someOtherFunction(value) {
alert(value);
}
someFunction("Foo");
As wybiral said, all you need is eval:
someFunction(link) {
someOtherFunction(eval('(div' + link + ')');
}
Basically what it does is evaluates the contents of a string as code. Obviously eval is a dangerous little tool since it allows executing arbitrary code so take care when using it.

Categories