Unfamiliar use of square brackets in calling a function - javascript

In the middle of this page, I find the code below.
var plus = function(x,y){ return x + y };
var minus = function(x,y){ return x - y };
var operations = {
'+': plus,
'-': minus
};
var calculate = function(x, y, operation){
return operations[operation](x, y);
}
calculate(38, 4, '+');
calculate(47, 3, '-');
Now while I can trace how it works, I've never seen this use of square brackets before. It certainly doesn't look like it's creating an array or referencing a member of an array. Is this common? If so, where are some other examples?

It is a dictionary access, which is like an array, but with a key instead of a numeric index.
operations['+'] will evaluate to the function plus, which is then called with the arguments plus(x,y).

It's called bracket notation.
In JavaScript you can use it to access object properties.

here operations is an object where the symbols + and - refers to two functions.
operations[operation] will return a reference to function plus where value of operation is + and then the following () will invoke the function

operations is an object and when you do operations[property] you will get the associated function and then you are passing the operands as x and y.
operations['+'] is function (x,y){ return x + y } which is plus
operations['-'] is function (x,y){ return x - y } which is minus

My JavaScript book says that object properties need be named with arbitrary names. But '+' and '-' are not names. From the original question, it is inferred that object properties just need be keyed, not named.

Related

How to extend Number in TypeScript by adding a function similar to ++

I would like to extend Number with a plusPlus2 function that will increment the number by 2.
The problem is that I don't know how to assign the result back to the number in the extension function. Something like:
Number.prototype.plusPlus2 = function() {
this = this + 2;
}
And the usage would be:
x = 1;
x.plusPlus2(); // expect x to be 3
Primitives (numbers, strings, booleans) are immutable in javascript.
So anytime you change a primitive, you need to assign it to another variable (or even reassign it to itself).
That being said, you cannot do what you propose, you need to return a new value, containing the value you want, let's say:
Number.prototype.plusplus2 = function() {
return this + 2;
}
And then reassign it:
let x = 5;
x = x.plusplus2();
Then, you may be wondering: how x++ works?
And the answer is, x++ is a syntax sugar for x = x + 1, meaning that, in fact, you are not changing x, but instead, adding 1 to x and reassigning it to itself.
You cannot. That has various reasons:
1) this is read only, as you don't expect it to change during the execution of a method.
2) What you access with this is a Number object that wraps the primitive number. It gets thrown away after the call. So even if you could change the internal value property containing the number, the value of x won't change.
Number.prototype.example = function() { this.stuff = "you see" };
let x = 1; // primitive
x.example(); // wrapped object
// wrapped object gets thrown away
console.log(x.stuff); // undefined, another wrapped object
3) Numbers are immutable and primitive. You can write a new number into x, but you can't turn all 1s into 3s.
You could create a new number, but then you have the problem that you have to write that number into x.
Number.prototype.plus2 = function() { return this + 2 };
let x = 1;
x = x.plus2();
Number.prototype.plus2 = function() {
return this + 2
}
let a = 2
console.log(a.plus2())

Supporting arrays in custom functions with multiple inputs

I have a custom function in my google apps script that takes two variables. I want this function to take two arrays for parameters, but the standard approach of putting "if input.map, return input.map(function)" doesn't work with two variables.
I have tried recursing through the inputs, but since there are two in the function, it does not work with both.
this is not the function i am using, but it has the same problem.
function multiply(x,y)
{
if (x.map){
return x.map(multiply)
}
if (y.map){
return y.map(multiply)
}
return x * y
}
I expect the formula to take two arrays (i.e. A1:A5, B1:B5) and perform the function on each variable -- i.e. returning A1 * B1, A2 * B2 etc.
Issue:
multiply receives two arguments. When multiply is provided as a function argument to Array.map, the first argument will be the element of the array on which map is called and the second argument will be the element's index.
Solution:
Use map only on the first array x and then use elements from the corresponding second array y
Snippet:
function multiply(x, y) {
if (x.map) {
return x.map(function(xEl, i) {
yEl = y.map ? y[i] : y; // corresponding y Element
return multiply(xEl, yEl);
});
}
if (y.map) {//used, when y is a array and x is number
return multiply(y, x);
}
return x * y;// default
}
a = [[1],[2]];
b= [[3],[4]];
c= [[5,6],[7,8]];
d= [[1,2],[3,4]];
console.log(JSON.stringify(multiply(a,b)));
console.log(JSON.stringify(multiply(a,5)));
console.log(JSON.stringify(multiply(5,b)));
console.log(JSON.stringify(multiply(c,d)));
console.log(JSON.stringify(multiply(c,2)));
console.log(JSON.stringify(multiply(a,c))); //trims c
console.log(JSON.stringify(multiply(c,a)));//throws error
References:
Array#map

Javascript: Pass Hash Key as Parameter

I have a hash called 'tag' with several keys, including width, height, x, and y. I also have this function:
function invertCoordinates(measure, coordinate){
tag.measure = tag.measure * -1;
tag.coordinate = tag.coordinate - tag.measure;
}
In which I want to pass tag's keys:
invertCoordinates(width, x);
or
invertCoordinates(height, y);
Unfortunately, I can't pass keys in this manner. Is there some other way to accomplish this?
Can you do:
function invertCoordinates(measure, coordinate){
tag[measure] = tag[measure] * -1;
tag[coordinate] = tag[coordinate] - tag[measure];
}
where measure and coordinate are strings? For instance:
invertCoordinates("width", "x");
Use the array-access notation (tag[measure]) and pass the keys as strings: invertCoordinates('width', 'x')

Optimize custom Object Property in Array with Javascript

Look at the 3 lines of code within this Javascript function. Assume that y will always be a String:
function example(x, y) {
var s = {};
s[y] = x;
return s;
}
Bearing in mind the following:
Without wrapping it further within a function
Without using ;
Is it possible to condense the 3 lines of code into one?
Yes, with a little ugly code:
function example(x, y, s) {
return (s = {})[y] = x, s;
}
The extra parameter s is not passed into the function, it's only there to be declared as a variable, so you don't need the extra line var s;. (If you don't declare it locally it becomes a global variable, which is bad practice.)
The value of the assignment s = {} is what's assigned, so you can make the assignment and then continue using the value in the expression.
The comma operator returns the last value, e.g. (1,2) returns the value 2. That way you can add , s to the expression to make it return s.
Edit:
Another variation is using s as a variable in a for loop, and exit out of the loop:
function example(x, y) {
for(var s = {}; s[y] = x, true;) return s;
}
Is using function cheating? :)
function example(x, y) {
return new function () { this[y] = x; };
}
There is always evil eval:
function example(x, y) {
return eval('({' + y + ':"' + x + '"})');
}
But I still don't see the point in this.

Javascript: passing multiple arguments as a single variable

is it possible to pass multiple arguments using a single variable? For example, if I wanted to do something like:
function foo(x,y){
document.write("X is " + x);
document.write("Y is " + y);
}
var bar = "0,10";
foo(bar);
The example above is an simplified example of what I was trying to do. It doesn't work (because the "bar" is detected as a single argument). I know that there are easier ways to implement this using arrays.
So, I ask this question mostly out of curiosity - is it possible to get the "bar" variable to be detected as not one, but 2 arguments?
Thanks!
function foo(thing) {
document.write("X is " + thing.x);
document.write("Y is " + thing.y);
}
var bar = {x:0, y:10};
foo(bar);
What you're asking for is impossible. If you want to pass multiple values in a single argument, use an Array or an Object. If you really must use a string, you'll have to call split() to break the argument string into an array.
function Add (a, b, c) {
return a + b + c;
}
var nums = [1, 2, 4];
var sum = Add.apply (null, nums);
variable-length argument list:
function Add () {
var sum = 0;
for (var i = 0; i < arguments.length; i++) {
sum += arguments[i];
}
return sum;
}
var n = Add (1, 2, 3, 4, 5);
Reference: apply method (Function object)
Sure, this is common to pass an object for options
function foo(options){
//...
}
then you can pass in anything...
var opts = {};//create an object
opts['x'] = 5;//set whatever properties you want
opts['y'] = 23;
opts['border'] = 3;
foo(opts);//pass 1 argument, with as many values as you want
Often these are defined inline, especially if the values are not needed outside of the method call.
foo({'x':5,'y':23,'border':3});
Not really.
You could do:
window.foo.apply(window, bar.split(','));
(Apply lets you pass an array of arguments instead of each argument separately)
… but the phrase "ugly" comes to mind.
You may use this:
var bar = [0,10]; // creates an array
foo(bar);
function foo(arg){
document.write("X is " + arg[0]);
document.write("Y is " + arg[1]);
}
No, but you could pass a an array or object:
function foo(options){
document.write("X is " + options.x);
document.write("Y is " + options.y);
}
var bar = {x: 0, y:10};
No, it's not possible. You could put two arguments in an array, but an array is still one variable. Then you would need to rewrite the function to accept one variable, and treat it as an array, like this:
function foo(x){
document.write("X is " + x[0]);
document.write("Y is " + x[1]);
}
Basically, a function accepts variables as arguments and, no matter what kind of variable you pass it, each variable is still only one variable - there's no way to get a single variable to be recognized as multiple arguments. An array is one variable, a JSON object is one variable, etc. These things have multiple parts to them, but they're encapsulated by a single variable.
How about? (For ES6+)
function foo({x, y}){
document.write("X is " + x);
document.write("Y is " + y);
}
and call it with:
foo({x:10, y:5})
There is a downside to using a single structured argument over multiple arguments, and that is with multiple arguments you can use /** in may IDEs to generate a method header which will display an #param for each argument.
But if you only have one argument then you will lose the niceness of a description for each argument and hence less useful intelli-sense in the IDE as it wont pick up the docuemntation of the structure's properties.
/**
* Do stuff
* #param {*} param0 - A structure containing the blah, blah blah data
*/
function foo({x, y}){
instead of..
/**
*
* #param {*} x - The value for blah
* #param {*} y - the value for blah-blah
*/
foo1(x, y){
To directly answer your question, no. It's worth noting that the way you have bar defined it's only one value, a string containing "0,10".
function myFunction(a,b){
//do stuff with a and b here
}
myFunction(1,'text')
or...
<a onClick="myFunction(1,'text');"
There's an article on the issue here.

Categories

Resources