Named array element used in function definition - javascript

Recently I discovered that this syntax works in JavaScript (Chrome 53):
function foo([param1]) { // Function argument is declared as array and param1 is used as variable? What is the name of this syntax?
console.log(param1);
}
foo(['TestParameter1']); // Case 1 - works. Output: TestParameter1
foo('TestParameter1'); // Case 2 - works??? Why? Output: TestParameter1
foo(123); // Case 3 - does not work - VM860:1 Uncaught TypeError: undefined is not a function(…)
Result => TestParameter1 // this is the result
I see that param1 can be used as variable that references item with index 0 in the first argument (declared as array).
My questions are:
1) How is this syntax named (the [param1] part that lets you use param1 as variable)?
2) Why does "Case 2" work? Is there any automatic conversion?

As #Xufox pointed out, this works because of destructuring (array destructuring, to be more specific). Your second example works because a string is an array-like object, so you get T, which is param1[0]. Numbers are not arrays (or even array-like), so the the engine fails to destructure the argument.
If you coerce your number to a string it will work:
foo((123).toString());

This seems to be destructuring as #Xufox correctly pointed out.
Function parameters can in fact have destructuring:
go to https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment
Search for this text: Pulling fields from objects passed as function parameter
Now the above shows an example of another kind of destructuring, example given below:
function userId({id}) {
return id;
}
var user = {
id: 42,
displayName: "jdoe"
};
console.log("userId: " + userId(user)); // "userId: 42"
however, I assume it applies to this as well:
function foo([param1]) {
console.log(param1);
}
Difference between integers and strings in this behaviour:
console.log('123'); //works, outputs 1, '123' = ['1', '2', '3'] of chars
console.log(['123']); //works, outputs 123
console.log([123]); //works, outputs 123
console.log(123); //error
In the above example, since strings are nothing but an array of chars, its perfectly fine that it works actually.

Exactly as said by those brilliant folks above. Here's how the computer reads it:
foo('testParamater1') = foo(['testParamater1']);
but...
foo(123) = foo([[1,2,3]);
Unfortunately for your specific use case, not the same. Sorry!

Related

Invoking Javascript array methods without the use of parentheses [duplicate]

I'm not sure how to explain this, but when I run
console.log`1`
In google chrome, I get output like
console.log`1`
VM12380:2 ["1", raw: Array[1]]
Why is the backtick calling the log function, and why is it making a index of raw: Array[1]?
Question brought up in the JS room by Catgocat, but no answers made sense besides something about templating strings that didn't really fit why this is happening.
It is called Tagged Template in ES-6 more could be read about them Here, funny I found the link in the starred section of the very chat.
But the relevant part of the code is below (you can basically create a filtered sort).
function tag(strings, ...values) {
assert(strings[0] === 'a');
assert(strings[1] === 'b');
assert(values[0] === 42);
return 'whatever';
}
tag `a${ 42 }b` // "whatever"
Basically, its merely tagging the "1" with console.log function, as it would do with any other function. The tagging functions accept parsed values of template strings and the values separately upon which further tasks can be performed.
Babel transpiles the above code to
var _taggedTemplateLiteralLoose = function (strings, raw) { strings.raw = raw; return strings; };
console.log(_taggedTemplateLiteralLoose(["1"], ["1"]));
As you can see it in the example above, after being transpiled by babel, the tagging function (console.log) is being passed the return value of the following es6->5 transpiled code.
_taggedTemplateLiteralLoose( ["1"], ["1"] );
The return value of this function is passed to console.log which will then print the array.
Tagged template literal:
The following syntax:
function`your template ${foo}`;
Is called the tagged template literal.
The function which is called as a tagged template literal receives the its arguments in the following manner:
function taggedTemplate(strings, arg1, arg2, arg3, arg4) {
console.log(strings);
console.log(arg1, arg2, arg3, arg4);
}
taggedTemplate`a${1}b${2}c${3}`;
The first argument is an array of all the individual string characters
The remaining argument correspond with the values of the variables which we receive via string interpolation. Notice in the example that there is no value for arg4 (because there are only 3 times string interpolation) and thus undefined is logged when we try to log arg4
Using the rest parameter syntax:
If we don't know beforehand how many times string interpolation will take place in the template string it is often useful to use the rest parameter syntax. This syntax stores the remaining arguments which the function receives into an array. For example:
function taggedTemplate(strings, ...rest) {
console.log(rest);
}
taggedTemplate `a${1}b${2}c${3}`;
taggedTemplate `a${1}b${2}c${3}d${4}`;
Late to the party but, TBH, none of the answers give an explanation to 50% of the original question ("why the raw: Array[1]")
1. Why is it possible to call the function without parenthesis, using backticks?
console.log`1`
As others have pointed out, this is called Tagged Template (more details also here).
Using this syntax, the function will receive the following arguments:
First argument: an array containing the different parts of the string that are not expressions.
Rest of arguments: each of the values that are being interpolated (ie. those which are expressions).
Basically, the following are 'almost' equivalent:
// Tagged Template
fn`My uncle ${uncleName} is ${uncleAge} years old!`
// function call
fn(["My uncle ", " is ", " years old!"], uncleName, uncleAge);
(see point 2. to understand why they're not exactly the same)
2. Why the ["1", raw: Array[1]] ???
The array being passed as the first argument contains a property raw, wich allows accessing the raw strings as they were entered (without processing escape sequences).
Example use case:
let fileName = "asdf";
fn`In the folder C:\Documents\Foo, create a new file ${fileName}`
function fn(a, ...rest) {
console.log(a); //In the folder C:DocumentsFoo, create a new file
console.log(a.raw); //In the folder C:\Documents\Foo, create a new file
}
What, an array with a property ??? ???
Yes, since JavaScript arrays are actually objects, they can store properties.
Example:
const arr = [1, 2, 3];
arr.property = "value";
console.log(arr); //[1, 2, 3, property: "value"]

Why can functions be called using `` operator in JavaScript? [duplicate]

I'm not sure how to explain this, but when I run
console.log`1`
In google chrome, I get output like
console.log`1`
VM12380:2 ["1", raw: Array[1]]
Why is the backtick calling the log function, and why is it making a index of raw: Array[1]?
Question brought up in the JS room by Catgocat, but no answers made sense besides something about templating strings that didn't really fit why this is happening.
It is called Tagged Template in ES-6 more could be read about them Here, funny I found the link in the starred section of the very chat.
But the relevant part of the code is below (you can basically create a filtered sort).
function tag(strings, ...values) {
assert(strings[0] === 'a');
assert(strings[1] === 'b');
assert(values[0] === 42);
return 'whatever';
}
tag `a${ 42 }b` // "whatever"
Basically, its merely tagging the "1" with console.log function, as it would do with any other function. The tagging functions accept parsed values of template strings and the values separately upon which further tasks can be performed.
Babel transpiles the above code to
var _taggedTemplateLiteralLoose = function (strings, raw) { strings.raw = raw; return strings; };
console.log(_taggedTemplateLiteralLoose(["1"], ["1"]));
As you can see it in the example above, after being transpiled by babel, the tagging function (console.log) is being passed the return value of the following es6->5 transpiled code.
_taggedTemplateLiteralLoose( ["1"], ["1"] );
The return value of this function is passed to console.log which will then print the array.
Tagged template literal:
The following syntax:
function`your template ${foo}`;
Is called the tagged template literal.
The function which is called as a tagged template literal receives the its arguments in the following manner:
function taggedTemplate(strings, arg1, arg2, arg3, arg4) {
console.log(strings);
console.log(arg1, arg2, arg3, arg4);
}
taggedTemplate`a${1}b${2}c${3}`;
The first argument is an array of all the individual string characters
The remaining argument correspond with the values of the variables which we receive via string interpolation. Notice in the example that there is no value for arg4 (because there are only 3 times string interpolation) and thus undefined is logged when we try to log arg4
Using the rest parameter syntax:
If we don't know beforehand how many times string interpolation will take place in the template string it is often useful to use the rest parameter syntax. This syntax stores the remaining arguments which the function receives into an array. For example:
function taggedTemplate(strings, ...rest) {
console.log(rest);
}
taggedTemplate `a${1}b${2}c${3}`;
taggedTemplate `a${1}b${2}c${3}d${4}`;
Late to the party but, TBH, none of the answers give an explanation to 50% of the original question ("why the raw: Array[1]")
1. Why is it possible to call the function without parenthesis, using backticks?
console.log`1`
As others have pointed out, this is called Tagged Template (more details also here).
Using this syntax, the function will receive the following arguments:
First argument: an array containing the different parts of the string that are not expressions.
Rest of arguments: each of the values that are being interpolated (ie. those which are expressions).
Basically, the following are 'almost' equivalent:
// Tagged Template
fn`My uncle ${uncleName} is ${uncleAge} years old!`
// function call
fn(["My uncle ", " is ", " years old!"], uncleName, uncleAge);
(see point 2. to understand why they're not exactly the same)
2. Why the ["1", raw: Array[1]] ???
The array being passed as the first argument contains a property raw, wich allows accessing the raw strings as they were entered (without processing escape sequences).
Example use case:
let fileName = "asdf";
fn`In the folder C:\Documents\Foo, create a new file ${fileName}`
function fn(a, ...rest) {
console.log(a); //In the folder C:DocumentsFoo, create a new file
console.log(a.raw); //In the folder C:\Documents\Foo, create a new file
}
What, an array with a property ??? ???
Yes, since JavaScript arrays are actually objects, they can store properties.
Example:
const arr = [1, 2, 3];
arr.property = "value";
console.log(arr); //[1, 2, 3, property: "value"]

functionName`string` - what does the syntax work? [duplicate]

I'm not sure how to explain this, but when I run
console.log`1`
In google chrome, I get output like
console.log`1`
VM12380:2 ["1", raw: Array[1]]
Why is the backtick calling the log function, and why is it making a index of raw: Array[1]?
Question brought up in the JS room by Catgocat, but no answers made sense besides something about templating strings that didn't really fit why this is happening.
It is called Tagged Template in ES-6 more could be read about them Here, funny I found the link in the starred section of the very chat.
But the relevant part of the code is below (you can basically create a filtered sort).
function tag(strings, ...values) {
assert(strings[0] === 'a');
assert(strings[1] === 'b');
assert(values[0] === 42);
return 'whatever';
}
tag `a${ 42 }b` // "whatever"
Basically, its merely tagging the "1" with console.log function, as it would do with any other function. The tagging functions accept parsed values of template strings and the values separately upon which further tasks can be performed.
Babel transpiles the above code to
var _taggedTemplateLiteralLoose = function (strings, raw) { strings.raw = raw; return strings; };
console.log(_taggedTemplateLiteralLoose(["1"], ["1"]));
As you can see it in the example above, after being transpiled by babel, the tagging function (console.log) is being passed the return value of the following es6->5 transpiled code.
_taggedTemplateLiteralLoose( ["1"], ["1"] );
The return value of this function is passed to console.log which will then print the array.
Tagged template literal:
The following syntax:
function`your template ${foo}`;
Is called the tagged template literal.
The function which is called as a tagged template literal receives the its arguments in the following manner:
function taggedTemplate(strings, arg1, arg2, arg3, arg4) {
console.log(strings);
console.log(arg1, arg2, arg3, arg4);
}
taggedTemplate`a${1}b${2}c${3}`;
The first argument is an array of all the individual string characters
The remaining argument correspond with the values of the variables which we receive via string interpolation. Notice in the example that there is no value for arg4 (because there are only 3 times string interpolation) and thus undefined is logged when we try to log arg4
Using the rest parameter syntax:
If we don't know beforehand how many times string interpolation will take place in the template string it is often useful to use the rest parameter syntax. This syntax stores the remaining arguments which the function receives into an array. For example:
function taggedTemplate(strings, ...rest) {
console.log(rest);
}
taggedTemplate `a${1}b${2}c${3}`;
taggedTemplate `a${1}b${2}c${3}d${4}`;
Late to the party but, TBH, none of the answers give an explanation to 50% of the original question ("why the raw: Array[1]")
1. Why is it possible to call the function without parenthesis, using backticks?
console.log`1`
As others have pointed out, this is called Tagged Template (more details also here).
Using this syntax, the function will receive the following arguments:
First argument: an array containing the different parts of the string that are not expressions.
Rest of arguments: each of the values that are being interpolated (ie. those which are expressions).
Basically, the following are 'almost' equivalent:
// Tagged Template
fn`My uncle ${uncleName} is ${uncleAge} years old!`
// function call
fn(["My uncle ", " is ", " years old!"], uncleName, uncleAge);
(see point 2. to understand why they're not exactly the same)
2. Why the ["1", raw: Array[1]] ???
The array being passed as the first argument contains a property raw, wich allows accessing the raw strings as they were entered (without processing escape sequences).
Example use case:
let fileName = "asdf";
fn`In the folder C:\Documents\Foo, create a new file ${fileName}`
function fn(a, ...rest) {
console.log(a); //In the folder C:DocumentsFoo, create a new file
console.log(a.raw); //In the folder C:\Documents\Foo, create a new file
}
What, an array with a property ??? ???
Yes, since JavaScript arrays are actually objects, they can store properties.
Example:
const arr = [1, 2, 3];
arr.property = "value";
console.log(arr); //[1, 2, 3, property: "value"]

Backticks (`…`) calling a function in JavaScript

I'm not sure how to explain this, but when I run
console.log`1`
In google chrome, I get output like
console.log`1`
VM12380:2 ["1", raw: Array[1]]
Why is the backtick calling the log function, and why is it making a index of raw: Array[1]?
Question brought up in the JS room by Catgocat, but no answers made sense besides something about templating strings that didn't really fit why this is happening.
It is called Tagged Template in ES-6 more could be read about them Here, funny I found the link in the starred section of the very chat.
But the relevant part of the code is below (you can basically create a filtered sort).
function tag(strings, ...values) {
assert(strings[0] === 'a');
assert(strings[1] === 'b');
assert(values[0] === 42);
return 'whatever';
}
tag `a${ 42 }b` // "whatever"
Basically, its merely tagging the "1" with console.log function, as it would do with any other function. The tagging functions accept parsed values of template strings and the values separately upon which further tasks can be performed.
Babel transpiles the above code to
var _taggedTemplateLiteralLoose = function (strings, raw) { strings.raw = raw; return strings; };
console.log(_taggedTemplateLiteralLoose(["1"], ["1"]));
As you can see it in the example above, after being transpiled by babel, the tagging function (console.log) is being passed the return value of the following es6->5 transpiled code.
_taggedTemplateLiteralLoose( ["1"], ["1"] );
The return value of this function is passed to console.log which will then print the array.
Tagged template literal:
The following syntax:
function`your template ${foo}`;
Is called the tagged template literal.
The function which is called as a tagged template literal receives the its arguments in the following manner:
function taggedTemplate(strings, arg1, arg2, arg3, arg4) {
console.log(strings);
console.log(arg1, arg2, arg3, arg4);
}
taggedTemplate`a${1}b${2}c${3}`;
The first argument is an array of all the individual string characters
The remaining argument correspond with the values of the variables which we receive via string interpolation. Notice in the example that there is no value for arg4 (because there are only 3 times string interpolation) and thus undefined is logged when we try to log arg4
Using the rest parameter syntax:
If we don't know beforehand how many times string interpolation will take place in the template string it is often useful to use the rest parameter syntax. This syntax stores the remaining arguments which the function receives into an array. For example:
function taggedTemplate(strings, ...rest) {
console.log(rest);
}
taggedTemplate `a${1}b${2}c${3}`;
taggedTemplate `a${1}b${2}c${3}d${4}`;
Late to the party but, TBH, none of the answers give an explanation to 50% of the original question ("why the raw: Array[1]")
1. Why is it possible to call the function without parenthesis, using backticks?
console.log`1`
As others have pointed out, this is called Tagged Template (more details also here).
Using this syntax, the function will receive the following arguments:
First argument: an array containing the different parts of the string that are not expressions.
Rest of arguments: each of the values that are being interpolated (ie. those which are expressions).
Basically, the following are 'almost' equivalent:
// Tagged Template
fn`My uncle ${uncleName} is ${uncleAge} years old!`
// function call
fn(["My uncle ", " is ", " years old!"], uncleName, uncleAge);
(see point 2. to understand why they're not exactly the same)
2. Why the ["1", raw: Array[1]] ???
The array being passed as the first argument contains a property raw, wich allows accessing the raw strings as they were entered (without processing escape sequences).
Example use case:
let fileName = "asdf";
fn`In the folder C:\Documents\Foo, create a new file ${fileName}`
function fn(a, ...rest) {
console.log(a); //In the folder C:DocumentsFoo, create a new file
console.log(a.raw); //In the folder C:\Documents\Foo, create a new file
}
What, an array with a property ??? ???
Yes, since JavaScript arrays are actually objects, they can store properties.
Example:
const arr = [1, 2, 3];
arr.property = "value";
console.log(arr); //[1, 2, 3, property: "value"]

About scope of arguments and document.writeln in function

I'm reading "JavaScripts The Good Parts"(by Douglas Crockford). It's good.
I can not understand following code. It's working correctly. But I can not understand how it works.
There are 5 questions about this code.
values of arguments (I checked them as [A], [B] in comment)
reason that document.writeln does not work(i.e. show nothing) in function (I checked test position as [C], [D] in comment)
result of slice in this code (in [A], [B])
values of variable args (in [A], [B])
reason that document.writeln shows 'undefined' (in comment [E] )
After showing that code, I will explain more.
var myTest = {};
Function.prototype.method = function(name, func) {
if(!this.prototype[name])
{
this.prototype[name]=func;
}
};
Function.method('bind', function(that) {
var method = this,
slice = Array.prototype.slice,
args = slice.apply(arguments, [1]); //[A] value of arguments and args
//-------------------------------
//[C] following document.writeln do not work. why?
document.writeln("<C>arguments[0]:", arguments[0]);
document.writeln("<C>arguments[1]:", arguments[1]);
document.writeln("<C>args:",args);
myTest.str1 = 1;
myTest.str2 = "ABC";
document.writeln("<C>str1:", myTest.str1);
document.writeln("<C>str2:", myTest.str2);
//-------------------------------
return function(){
//-------------------------------
//[D] following document.writeln do not work. why?
document.writeln("<D>arguments[0]:", arguments[0]);
document.writeln("<D>arguments[1]:", arguments[1]);
document.writeln("<D>args:",args);
myTest.str3 = 2;
myTest.str4 = "DEF";
document.writeln("<D>str3:", myTest.str3);
document.writeln("<D>str4:", myTest.str4);
//-------------------------------
return method.apply(that, args.concat(slice.apply(arguments, [0]))); //[B] value of arguments and args
};
});
var x= function(){
return this.value;
}.bind({value:666});
//-------------------------------
document.writeln("str1:", myTest.str1, "<br/>"); //[E]show undefined. why?
document.writeln("str2:", myTest.str2, "<br/>"); //[E]show undefined. why?
document.writeln("str3:", myTest.str3, "<br/>"); //[E]show undefined. why?
document.writeln("str4:", myTest.str4, "<br/>"); //[E]show undefined. why?
//-------------------------------
alert(x()); //666 -> no problem
document.writeln in [C], [D], [E] was for testing. But they don't work as I expected.
Alerting '666' operates well. (No problem)
Help me, please...
----------- after removing if-confition in Function.prototype.method I got following result
[C]arguments[0]:[object Object]
[C]arguments[1]:undefined
[C]args:
[C]str1:1
[C]str2:ABC
str0C:[object Object]
str1C:undefined
str0D:undefined
str1D:undefined
str1:1
str2:ABC
str3:undefined
str4:undefined
[D]arguments[0]:undefined
[D]arguments[1]:undefined
[D]args:
[D]str1:2
[D]str2:DEF
str0C:[object Object]
str1C:undefined
str0D:undefined
str1D:undefined
str1:1
str2:ABC
str3:2
str4:DEF
Now, I wonder real value of arguments in [C], [D], the contents of array...
Using JSON.stringify(arguments[0])), I finally got the real value of arguments.
[C]arguments[0]:{"value":666}
This is what I really want.
[C]arguments[1], [D]arguments[0], [D]arguments[1] do not have values. So they are 'undefined', right.
Now, I want to know what "args = slice.apply(arguments, [1]);" does in [A].
args = slice.apply(arguments, [1]);
As I know, slice returns copy of array. Because we use apply, slice works using arguments as this, and [1] as array of argument. At this time, arguments have only one item {"value":666"}. slice(start, end) returns copy of array which starts from 'start' and ends with 'end'. Then, in this case slice.apply(arguments, [1]) must return copy of arguments which starts from 1. But as we know arguments have only 1 item, so arguments[1] does not exist.(arguments[0], {value:666} exists.) Then how this work? args is undefined. What does this do? Is there anything that I overlooked?
In [B] it returns "method.apply(that, args.concat(slice.apply(arguments, [0])));".
return method.apply(that, args.concat(slice.apply(arguments, [0])));
In this, [0] is array of argument. 0.. Why zero? And arguments is undefined. Um... Then this returns arguments[0]? And that is {value:666}? And alert '666'?
I got it..
arguments in [A] is arguments of bind function
arguments in [B] is arguments of x function
Right?
Now there is one (maybe last) question .. ^^
When I call document.writeln.bind(document,"TEST") , what is 'that' in Function.method('bind', function(that)?
'that' is document? or 'that' is [document, "TEST"]
Function.prototype.method = function(name, func) {
if(!this.prototype[name])
…is your problem. You're not overwriting existing functions - and Function.prototype.bind does already exist (and has the same result as the one you defined, but without logging). That way, you don't overwrite it with your custom implementation, and none of your document.writeln calls or myTest assignments will be executed.
You can remove the if-condition for test purposes, and it will work. You should be able to answer the other questions yourself, once you see in the output what happens.
Now, I wonder real value of arguments in [C], [D], the contents of array...
There's only one object in question: {value:666} :-) You can output that by using JSON.stringify:
document.writeln("<C>arguments[0]:", JSON.stringify(arguments[0]));
…
[slicing] Then, in this case slice.apply(arguments, [1]) must return copy of arguments which starts from 1.
Yes. Btw it would've been easier to write slice.call(arguments, 1) - they're the same.
But as we know arguments have only 1 item, so arguments[1] does not exist.(arguments[0], {value:666} exists.) Then how this work? args is undefined.
Not undefined, but the empty array [].
What does this do? Is there anything that I overlooked?
It takes further, optional arguments to bind. You didn't pass any.
In [B] it returns "method.apply(that, args.concat(slice.apply(arguments, [0])));". In this, [0] is array of argument. 0.. Why zero?
Because you want to get all of the (optional) arguments to the bound function - slicing them from the beginning.
And arguments is undefined. Um... Then this returns arguments[0]? And that is {value:666}? And alert '666'?
arguments is not undefined, but has length 0, so the whole args.concat(…) evaluates to an empty array. that still points to the {value: 666}, yes - it is what will be passed for the this keyword.
So what are all these optional arguments about?
In your x example you've only used this, your function did not really have any arguments. But it could have - let's try one that has more arguments, like console.log:
var logger = console.log.bind(console, "Here:");
logger(); // Here:
logger(5); // Here: 5
logger({value:666}); // Here: {value: 666}
If you're not (yet) comfortable with the console, you could equally use document.writeln.bind(document, ….

Categories