I noticed in several MDN Array method shims, such as this one on line 7, that they use the following syntax:
var t = Object(this);
Where this is an array. Not only does it not hint in my validator, I’m also clueless as to what it does.
Can anyone shed a light?
As far as I can tell, the only use of it in there is to cover the case when you pass a string literal to Array.prototype.indexOf. If you remove it and pass a string in you get an error:
TypeError: Cannot use 'in' operator to search for '0' in string
However, by casting the string literal to an instance of String, you end up with an object with a numerical property for each character of the string, and since it's a normal object, you can use the in operator on it and the method will return the index of the character in the string:
Array.prototype.indexOf.call("hello", "e"); // Returns 1
Here's an example with the cast to Object, and here's an example without it.
In more general cases, passing anything to the Object constructor will attempt to convert that thing to an object. So you can pass it a string literal and get an instance of String back, or pass it a numeric literal and get an instance of Number.
Related
the function returns 'Hello, world!'
it's very confusing to understand trim and bind inside an array as string.
f=''['trim']['bind']`Hello, world!`()
I hadn't seen something like this before. I found it very interesting so looked into how it works. Here's my attempt to explain:
''['trim'] -- The initial blank string '' has string methods like .trim() available to it. Using the bracket notation you can access the trim method with ''['trim'].
''['trim']['bind'] -- Rather than calling the trim method though (which would require adding () to the end), we call the .bind() method that is part of the prototype of trim, again using bracket notation. Bind takes its initial argument and binds it to the previous function (trim) as the 'this' keyword.
''['trim']['bind']`Hello, world!` -- The final piece here is passing the string 'Hello, world!' inside an array to the .bind() method. The notation here is a string literal being used as a tagged template. This allows a template literal to be used as an array argument to its preceding "tag", in this case the bound function. This is now equivalent to ['Hello, world!'].trim(). Trim coerces an array of strings to a string with each element separated by a comma. But as there is only 1 element, that single element is returned.
f=''['trim']['bind']`Hello, world!`() -- Calling the whole thing with () at the end results in trimming 'Hello, world!', which just returns the same string as there is nothing to actually trim. It was all just a ruse to get to the string method's prototype!
When I try to JSON.parse("foo"), I get an Error:
Uncaught SyntaxError: Unexpected token o in JSON at position 1
at JSON.parse (<anonymous>)
at <anonymous>:1:6
But, when I use JSON.parse('"foo"'), I can get the result as expected:
const value = JSON.parse('"foo"');
console.log(value)
So why does this happen?
You can find what makes valid JSON at json.org. JSON can represent null, booleans, numbers, strings, arrays and objects. For strings, they must be enclosed in double quotes.
JSON itself is a string format, so when you specify a string in JSON format, you need:
quotes to tell JavaScript you are specifying a string literal. Those quotes are not part of the string value itself; they are just delimiters.
double-quotes inside that string literal to follow the JSON syntax for the string data type.
So here are some examples of correct arguments for JSON.parse:
JSON.parse("true")
JSON.parse("false")
JSON.parse("null")
JSON.parse("42")
JSON.parse("[13]")
JSON.parse('"hello"')
JSON.parse('{"name": "Mary"}')
But not:
JSON.parse("yes")
JSON.parse("no")
JSON.parse("none")
JSON.parse('hello')
JSON.parse({"name": "Mary"})
Because the argument will be cast to string when it is not, the following will also work, but it is confusing (and useless):
JSON.parse(true)
JSON.parse(false)
JSON.parse(null)
JSON.parse(42)
This happens because JSON.parse() gives a value back by formatting the string given using the syntaxis to declare values in Javascript. Therefore using foo naked would be like casting an undefined variable.
Notice also that the notation uses double quotes " instead of single ones '. That's why JSON.parse('"foo"') works but JSON.parse("'foo'") won't.
Basically, I am trying to create an object like this by providing a string to JSON.parse():
a = {x:1}
// -> Object {x: 1}
Intuitively I tried:
a = JSON.parse('{x:1}')
// -> Uncaught SyntaxError: Unexpected token x
After some fiddling I figured out:
a = JSON.parse('{"x":1}')
// -> Object {x: 1}
But then I accidentally changed the syntax and bonus confusion kicked in:
a = JSON.parse("{'x':1}")
//-> Uncaught SyntaxError: Unexpected token '
So now I am looking for an explanation why
one must to quote the property name
the implementation accepts single quotes, but fails on double quotes
The main reason for confusion seems to be the difference between JSON and JavaScript objects.
JSON (JavaScript Object Notation) is a data format meant to allow data exchange in a simple format. That is the reason why there is one valid syntax only. It makes parsing much easier. You can find more information on the JSON website.
Some notes about JSON:
Keys must be quoted with "
Values might be strings, numbers, objects, arrays, booleans or "null"
String values must be quoted with "
JavaScript objects on the other hand are related to JSON (obviously), but not identical. Valid JSON is also a valid JavaScript object. The other way around, however, is not.
For example:
keys and values can be quoted with " or '
keys do not always have to be quoted
values might be functions or JavaScript objects
As pointed out in the comments, because that's what the JSON spec specifies. The reason AFAIK is that JSON is meant to be a data interchange format (language agnostic). Many languages, even those with hash literals, do not allow unquoted strings as hash table keys.
Usually, what I see is {"attribute":241241}
but writting this does exactly the same thing : {attribute:241241}.
Is {attribute:241241} considered bad practice and should be avoided or not?
{attribute:241241} does not validate using JSONLint, so yes, it is bad practice and should be avoided.
Further, if you look at the JSON spec at json.org, you will find that for objects the first value is always a string (indicated by double quotes).
You are confusing JSON with Object literal syntax, in Javascript doing
var o = {
"attribute":241241
};
is not JSON, but object literal. And yes, the quotes are useless there.
The JSON specification requires that keys be quoted, so the second form isn't valid JSON.
As Snakes and Coffee noted, it is a valid Javascript object literal (on which JSON is based), and some JSON parsers will accept it anyway. So it may work in some cases, but sooner or later you'll run into a perfectly functional JSON parser that rejects your non-quoted keys because they aren't valid per the spec.
As per the specification here, the names in name/value pairs must be of type string.
An object is an unordered collection of zero or more name/value pairs,
where a name is a string and a value is a string, number, boolean,
null, object, or array.
Javascript has a number of string manipulation operations which can be performed on it. So we have methods like concat(), slice(), match(), etc
My question is do all these string manipulation methods return a new string value as the result OR are there some methods which actually modify the actual string being used in the method ?
Strings in JavaScript (and many other languages) are implemented as immutable objects. This has a few beneficial properties:
It's thread safe, and more specifically,
Multiple references to the same string can be kept safely without having to worry that the value changes.
This also means that all string methods must return a new string if they aim to modify the original value.
The return value is a clone of the original string.
In other words, calling concat, match or slice will not modify the original string.
You can always refer to the MDN reference for documentation
But, to quote from the source
Concat
Combines the text of two or more strings and returns a new string.
Strings are immutable, and once they are created they even cannot be modified again.
Mdn:
Unlike in languages like C, JavaScript strings are immutable. This means that once a string is created, it is not possible to modify it. However, it is still possible to create another string based on an operation on the original string, for example, a substring of the original (by picking individual letters or using String.substr()) or a concatenation of two strings using the concatenation operator (+) or String.concat().
Therefore, yes. Every String operation returns a new String