What is this javascript code doing? - javascript

this.String = {
Get : function (val) {
return function() {
return val;
}
}
};
What is the ':' doing?

this.String = {} specifies an object. Get is a property of that object. In javascript, object properties and their values are separated by a colon ':'.
So, per the example, you would call the function like this
this.String.Get('some string');
More examples:
var foo = {
bar : 'foobar',
other : {
a : 'wowza'
}
}
alert(foo.bar); //alerts 'foobar'
alert(foo.other.a) //alerts 'wowza'

Others have already explained what this code does. It creates an object (called this.String) that contains a single function (called Get). I'd like to explain when you could use this function.
This function can be useful in cases where you need a higher order function (that is a function that expects another function as its argument).
Say you have a function that does something to each element of an Array, lets call it map. You could use this function like so:
function inc (x)
{
return x + 1;
}
var arr = [1, 2, 3];
var newArr = arr.map(inc);
What the map function will do, is create a new array containing the values [2, 3, 4]. It will do this by calling the function inc with each element of the array.
Now, if you use this method a lot, you might continuously be calling map with all sorts of arguments:
arr.map(inc); // to increase each element
arr.map(even); // to create a list of booleans (even or odd)
arr.map(toString); // to create a list of strings
If for some reason you'd want to replace the entire array with the same string (but keeping the array of the same size), you could call it like so:
arr.map(this.String.Get("my String"));
This will create a new array of the same size as arr, but just containing the string "my String" over and over again.
Note that in some languages, this function is predefined and called const or constant (since it will always return the same value, each time you call it, no matter what its arguments are).
Now, if you think that this example isn't very useful, I would agree with you. But there are cases, when programming with higher order functions, when this technique is used.
For example, it can be useful if you have a tree you want to 'clear' of its values but keep the structure of the tree. You could do tree.map(this.String.Get("default value")) and get a whole new tree is created that has the exact same shape as the original, but none of its values.

It assigns an object that has a property "Get" to this.String. "Get" is assigned an anonymous function, which will return a function that just returns the argument that was given to the first returning function. Sounds strange, but here is how it can be used:
var ten = this.String["Get"](10)();
ten will then contain a 10. Instead, you could have written the equivalent
var ten = this.String.Get(10)();
// saving the returned function can have more use:
var generatingFunction = this.String.Get("something");
alert(generatingFunction()); // displays "something"
That is, : just assigns some value to a property.

This answer may be a bit superflous since Tom's is a good answer but just to boil it down and be complete:-
this.String = {};
Adds an object to the current object with the property name of String.
var fn = function(val) {
return function() { return(val); }
}
Returns a function from a closure which in turn returns the parameter used in creating the closure. Hence:-
var fnInner = fn("Hello World!");
alert(fnInner()); // Displays Hello World!
In combination then:-
this.String = { Get: function(val) {
return function() { return(val); }
}
Adds an object to the current object with the property name of String that has a method called Get that returns a function from a closure which in turn returns the parameter used in creating the closure.
var fnInner = this.String.Get("Yasso!");
alert(fnInner()); //displays Yasso!

Related

How to use apply with currying?

I have code that is using currying to get the average on an array that results from concatenating two arrays: an n size array and an m size array.
var avg = function(...n){
let tot=0;
for(let i=0; i<n.length; i++){
tot += n[i];
}
return tot/n.length;
};
var spiceUp = function(fn, ...n){
return function(...m){
return fn.apply(this, n.concat(m));
}
};
var doAvg = spiceUp(avg, 1,2,3);
console.log(doAvg(4,5,6));
In this line return fn.apply(this, n.concat(m));, I don't understand why do we need to use apply. What is the object we are binding with the average function and why does just normal calling (return fn(n.concat(m));) not work?
In that example, this is not that important. It would also work if instead of this you would pass an empty object instead. It's just an example on how to use apply.
What you need to focus is on the second parameter n.concat(m). They key concept here is that passing an array as a second argument you are calling that function (fn) passing each value in the array as an argument.
About your second question: no, it won't work because fn expects several arguments (one per value to calculate the average) while by doing return fn(n.concat(m)); you are just passing one argument, an array containing all values
Maybe you would understand it better with a simpler example:
function sum3params(a,b,c){
return a+b+c;
}
console.log(sum3params([3,4,2])) // won't work
console.log(sum3params.apply(this, [3,4,2])) // will work ('this' is not important here)
For this use case, it does not. But consider the following:
var foo = {
bar: 3
};
var addBar = function(a, b) { return a + b + this.bar };
foo.add3AndBar = spiceUp(addBar, 3);
foo.add3AndBar(1); // 7
Using apply means that your spiceUp function can be applied to methods as well as normal functions. For more likely example, consider partially applying when defining a method on a prototype:
const ENV = "linux";
DoesSomePlatformSpecificStuff.prototype.getPath = spiceUp(ENV);
apply also will spread the gathered array of arguments back out into positional arguments which can also be done like so:
return fn(...n.concat(m));
Which can be simplified as
return fn(...n, ...m);
Which is equivalent to
return fn.apply(undefined, n.concat(m));

JavaScript Constructor Function Methods

I am wondering why I need the PhoneNumberFormatter.prototype.slice method below.
Why can't I just use slice(3,6).join('') inside my other methods without needing to add PhoneNumberFormatter.prototype.slice method? When the interpreter doesn't find the method on the PhoneNumberFormatter object, wouldn't it just look up the prototype chain to find slice and join on the Array prototype?
function PhoneNumberFormatter(numbers) {
this.numbers = numbers;
}
PhoneNumberFormatter.prototype.render = function() {
var string = '';
string += this.parenthesize(this.getAreaCode());
string += ' ';
string += this.getExchangeCode();
string += '-';
string += this.getLineNumber();
return string;
};
PhoneNumberFormatter.prototype.getAreaCode = function() {
return this.slice(0, 3);
};
PhoneNumberFormatter.prototype.getExchangeCode = function() {
return this.slice(3, 6);
};
PhoneNumberFormatter.prototype.getLineNumber = function() {
return this.slice(6)
};
PhoneNumberFormatter.prototype.parenthesize = function(string) {
return '(' + string + ')';
};
// why do I need the following method?
PhoneNumberFormatter.prototype.slice = function(start, end) {
return this.numbers.slice(start, end).join('');
};
var phoneNumberOne = new PhoneNumberFormatter([6, 5, 0, 8, 3, 5, 9, 1, 7, 2]);
phoneNumberOne.render()
I guess it was created to make the code cleaner and prevents code duplication.
As the use of the slice keyword in two different places seems to confuse you I'll explain briefly the differences.
In your prototype methods (e.g. getAreaCode, getExchangeCode, ...), the keyword this represents a PhoneNumberFormatter object. When you call this.slice() (in the methods), you are calling the slice method of this object hence the one created in your code.
But in your slice method (the one in your code), you are calling this.numbers.slice(). Here you call the slice method on an array (this.numbers). You are using the native array method slice.
You could write your methods like so and remove the slice method created in your code:
PhoneNumberFormatter.prototype.getAreaCode = function() {
return this.numbers.slice(0, 3).join('');
};
I think the main confusion you seem to have is the name of the method slice. This leads you to believe that it is the array method, but in fact it is not.
The slice method mentioned in your code is the slice method of the PhoneNumberFormatter, not the one of the array.
Because of this, the interpreter could never find the slice method in the prototype chain, because the prototype of the PhoneNumberFormatter would be object, and just calling slice would rather throw an error that the method is undefined.
The this.slice method refers to PhoneNumberFormatter.prototype.slice and this one will refer to it's own numbers property and will then call the slice method on the numbers Array.
Maybe it is simply easier to rename the code like:
function PhoneNumberFormatter( numberArr ) {
this.numbers = numberArr.slice(); // copy numbers
}
PhoneNumberFormatter.prototype.getAreaCode = function() {
return this.take(0, 3);
};
PhoneNumberFormatter.prototype.take = function() {
return Array.prototype.splice.apply( this.numbers, arguments ).join('');
};
var formatter = new PhoneNumberFormatter([0,1,2,3,4,5,6,7,8,9]);
console.log(formatter.getAreaCode());
Which maybe makes it more clear to you, that the take method is simply a utility method simplifying your code, cause be honest, why would you want to repeat for 5 different methods the slice and join part, and then take a potential risk of copying an error 5 times, or in case you need to change something, need to make the same change 5 times

lambda like matching on json object for javascript backbone?

not a front end SME....is there a javascript or backbone(_) equivalent of this java 8 lambda instead of looping over a JSON array and matching on "type"? :
{
"things": [
{
"type": "THE_OTHER_THING"
},
{
"type": "MY_THING"
}
]
}
.
thing theThing = things.stream().filter(x -> x.getType() == ThingType.MY_THING).findFirst().orElse(null);
Assuming you are looking to iterate through an array and only return objects with a given type, I would suggest the following:
For single or little use, you could simply create the function that asserts the type of your choice:
function isThing(jsonObject) {
return jsonObject.type === "THIS_THING";
}
Or to avoid hard coding:
var THING_TYPE = "THIS_THING";
function isThing(jsonObject) {
return jsonObject.type === THING_TYPE;
}
Then you can apply this function to an array using its filter method.
var filteredList = completeList.filter(isThing);
filter, as described on MDN Array.prototype.filter, takes a function as an argument and applies it to every element within the array. If the function returns true, the element is added to a new array. Once the passed function has been applied to each element, the filter function returns the new array.
The above choice may be practical if you are simply looking for one or two types. However, if you have many types for which you might want filters, you should consider abstracting this away slightly, like so:
function createFilterWithType(desiredType) {
// will return true if jsonObject is of desired type
var typeAsserter = function (jsonObject) {
return jsonObject.type === desiredType;
}
return typeAsserter;
}
// Create functions that assert if object is given type
var isThisThingType = createFilterWithType("THIS_THING");
var isOtherThingType = createFilterWithType("OTHER_THING");
// Data
var completeList = [
{type:"THIS_THING", id:0},
{type:"OTHER_THING", id:1}
];
// Data filtered by applying asserters to completeList
var thingTypeList = completeList.filter(isThisThingType);
// returns [{type:"THIS_THING", id:0}]
var otherTypeList = completeList.filter(isOtherThingType);
// returns [{type:"OTHER_THING", id:1}]
Alternatively, you can create the asserters and apply in a single step:
var thingTypeList = completeList.filter(createFilterWithType("THIS_THING"));
var otherTypeList = completeList.filter(createFilterWithType("OTHER_THING"));
Though you remove a few lines by doing so, you lose in performance as each invocation of filter requires the creation of the anonymous assertion function. Worse still, compacting your code this way can make it far more difficult to reason about.

In Javascript, why does array.map(String) return array of strings?

The list processing routine map on an array object is very convenient at times. Here's one of the handy ways to use it:
var numarr = [1,2,3,4];
console.log(numarr.map(String))
>>> ["1", "2", "3", "4"]
I took this for granted thus far. Today I was however puzzled by it. What the map function is returning above is an array of strings. We typically pass a function to map as argument. In above case we pass String object. String is implemented inside the Javascript implementation, so I don't know what kind of specialities it has. The above code works as if a new instance of String is created for each item in array.
If it's not clear, consider this. If I decide to implement an object in Javascript say MyString and pass it to map, I won't get the above behavior.
function MyString(x) { this.val = x; }
MyString.prototype.toString = function () { return String(this.val); };
var ms = new MyString(4)
console.log(String(ms));
>>> "4"
var arr = [1,2,3];
arr.map(MyString)
>>> [undefined, undefined, undefined]
Does anyone know why then arr.map(String) works the way it does?
Update: A comment I added below clarifies my question better.
At the end of the 2nd snippet, try console.log(val). You'll notice you've leaked a global:
var arr = [1,2,3];
arr.map(MyString);
console.log(val); // "3"
When using arr.map(MyString), you're calling that constructor as a function, without the new to create instances. And, since MyString doesn't return anything, you get undefined in the results. But, you've still set this.val, while this isn't an instance but is rather the global object.
String doesn't return undefined because it has a return when called without new:
When String is called as a function rather than as a constructor, it performs a type conversion.
Returns a String value (not a String object) computed by ToString(value). If value is not supplied, the empty String "" is returned.
You can imitate this with MyString by checking if this is an instance first, returning a new instance when this isn't one already:
function MyString(x) {
if (this instanceof MyString) {
this.val = x;
} else {
return new MyString(x);
}
}
var arr = [1, 2, 3];
arr.map(MyString); // [ {val: "1"}, {val: "2"}, {val: "3"} ]
Array.map returns an array whose elements are the value returned by applying the specified function to each value in the this array. String is a function; it returns a string. That's all there is to it.
Thats is because String is a function. It returns a string constructed from what is passed to it. For example, if you call String(100), it will return "100".

How to pass variable by reference in javascript? Read data from ActiveX function which returns more than one value

I have a ActiveX object which I want to use in the browser (javascript).
There is a function I want to call. Its prototype is:
function TOPOSFiscalPrinter.DirectIO(Command: Integer; var pData: Integer;
var pString: WideString): Integer;
So, the function returns three values: result code, pData and pString;
In javascript the function does not update the variables pData and pString;
function test()
{
var d=1, s="DIRECIO:";
var code = opos.DirectIO(1024, d, s);
alert(d); alert(s);
}
Variables d and s are not updated. They must be d=0 and s="ED123456";
How to read data from function which returns more than one value in javascript?
EDIT
Apparently, Javascript always passes parameters by value, never by reference.
Is there anything I can do to pass values by reference in Javascript, or
I will have to change my design to only rely on parameters passed by
value and on return values.
Primitive types, primarily strings/numbers/booleans are passed by value for efficiency purposes. Objects such as functions, objects, arrays and the like are passed by reference. You can create an object and pass it, eg { d:1, s:'directo' } and then change the values because you're passing a reference.
There is no support for output parameter in JavaScript. Pack what you want to return in an automation object, assign values to its properties and return it, or if your return value is already occupied, create a class that has properties you can assign to in your ActiveX and add a parameter whose type is the class. In your ActiveX you can use IDispatch/Ex to get/set the properties.
Primitives like int's or float's are always passed by value for performance reasons, but you can just wrap them into e.g. a Float32Array with just one element:
a = new Float32Array([123])
a[0]; // == 123
function ChangeA(a) {
a[0] = 333;
}
ChangeA(a)
a[0]; // == 333
Make a global variable or object. Or if you're worried about other funcs accessing and changing the variables then make a singleton. The other option is to return an object. Such as like this
function TOPOSFiscalPrinter.DirectIO(Command: Integer; var pData: Integer;
var pString: WideString): Integer;
function TOPOSFiscalPrinter.DirectIO(Command, pData, pString){
....
var pObj = {
d: 0,
s: '',
code: ''
}
pObj.d = pDataAltertedValue;
pObj.s = pStringAltertedValue;
pObj.code = code;
return pObj;
}
function test()
{
var d=1, s="DIRECIO:";
var r = opos.DirectIO(1024, d, s);
code = r.code;
d = r.d;
s = r.s;
alert(d); alert(s);
}

Categories

Resources