assignment in JS - javascript

This is a very basic JS question, but this "issue" drives me crazy.
From simple algebra I would expect that both first and the second statement are vaild. But the second is always throwing "Invalid assignment" error.
Does anyone have a good explanation for it?
fieldname1 = document.getElementById("emailID1");
document.getElementById("emailID2") = fieldname2;
Thanks so much,

Most common programming languages, including JavaScript, require that the left-hand side of an assignment (the "target") be something called an l-value. That means it's an expression that denotes a place to put a value. A simple variable name, or a reference to an object followed by .propertyName suffix, works as an l-value.
In your case, the function call return value is not an l-value, because JavaScript does not make that possible (some languages do). A function call is always an r-value, meaning something that appears on the right-hand side of an assignment.
Now, in your particular case, because getElementById() returns a reference to a DOM element, you can do something like this:
document.getElementById("something").name = "frederick";
The function still returns an r-value, but that .name works as a property reference and thus as an l-value.

The assignment operator resolves the right side of the equal sign and stores it in the variable on the left side, which is what is happening in the first line.
The second line is basically trying to take the value of a variable fieldname2 and store it in a function call document.getElementById("emailID2")
JavaScript doesn't know how to resolve that at runtime, so it's throwing an invalid assignment operation.
There's more information on assignment from MDN here:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Assignment_Operators

You can't assign a value to an object itself in this case.
document.getElementById("emailID2") = fieldname2;
As i guess you want to do something like this:
document.getElementById("emailID2").name = fieldname2;

Related

What's the difference between str.fun() / str.fun / fun(str) in JavaScript?

I tried googling but couldn't find a precise answer, so allow me to try and ask here. If the question does not seem proper, please let me know and I'll delete it.
In JS you've got three different way of writing certain build in functionalities:
str.length
str.toString()
parseInt(str)
I wonder if there is a reason behind these different ways of writing. As a new user I don't grasp why it couldn't be streamlined as: length(str) / toString(str) / parseInt(str) or with dot formulation.
I however think if I do know the reason behind these differences, it would give me a better understanding of JavaScript.
Length is one of the attributes of string in JavaScript. Hence you use string.length to get the length of the string.
toString is a function for string objects, hence we use stringobj.toString().
parsInt(str) is a global function which takes string as a parameter.
JavaScript is object-oriented, so there are functions or procedures which require first an object to use as this in their bodies. str.length is a property, both syntactically and semantically. It doesn't require any parameters and represents some quality of the object. obj.toString() is a method (a function attached to an object), which doesn't represent any characteristics of the object, but rather operates on its state, computes some new values, or changes the state of the object a lot. parseInt(str) is a "global" function, which represents an operation not attached to any type or object.
Under the hood, these three ways may be well implemented with just calling a function, passing this as the first parameter (like C# does, for example). The semantic difference is the important one.
So why not use just the third syntax, like for example PHP does? First, it doesn't bloat the global environment with lots of functions which only work for one specific case and type, allowing you to specify any new function you want without breaking the old functionality. Second, it ecourages you to use object-oriented concepts, because you can already see working objects and methods in the language, and can try to make something similar.
And why isn't parseInt a method? It can as well be str.toInt() without any issues, it's just the way JavaScript designers wanted it to be, although it seems also a bit logical to me to make it a static method Number.parseInt(str), because the behaviour of the function is relevant more to the Number type than the String type.
JavaScript is based around objects. Objects have properties (e.g. a User object may have name and age properties). These are what define the user and are related to the user. Properties are accessed via dot-notation or brackets notation (to access Eliott’s age, we’ll use either eliott.age or eliott['age'] — these are equivalent).
These properties can be of any type — String, Number, Object, you name it — even functions. Now the proper syntax to call a function in JS is to put round brackets: eliott.sayHello(). This snippet actually fetches Eliott’s sayHello property, and calls it right away.
You can see Eliott as a box of properties, some of which can be functions. They only exist within the box and have no meaning out of the box: what would age be? Whose age? Who’s saying hello?
Now some functions are defined at the global level: parseInt or isNaN for instance. These functions actually belong to the global box, named window (because legacy). You can also call them like that: window.parseInt(a, 10) or window.isNaN(a). Omitting window is allowed for brevity.
var eliott = {
name: 'Eliott',
age: 32,
sayHello: function () { console.log('Hello, I’m Eliott'); }
};
eliott.name; // access the `name` property
eliott.age; // access the `age` property
eliott.sayHello; // access the `sayHello` property
eliott.sayHello(); // access the `sayHello` property and calls the function
sayHello(eliott); // Reference error: `window.sayHello` is undefined!
Note: Some types (String, Number, Boolean, etc.) are not real objects but do have properties. That’s how you can fetch the length of a string ("hello".length) and reword stuff ("hello, Eliott".replace("Eliott", "Henry")).
Behaviour of these expressions is defined in ECMAScript grammar. You could read the specification to understand it thoroughly: ECMAScript2015 specification. However, as pointed out by Bergi, it's probably not the best resource for beginners because it doesn't explain anything, it just states how things are. Moreover I think it might be too difficult for you to be able to grasp concepts described in this specification because of the very formal language used.
Therefore I recommend to start with something way simpler, such as a very basic introduction to JavaScript: JavaScript Basics on MDN. MDN is a great resource.
But to answer your question just briefly:
str.length is accessing a property of the str object.
parseInt(str) is a function call
str.toString() is a call of a function which is a property of the str object. Such functions are usually named methods.
Functions and methods are in fact very similar but one of the differences (except for the obvious syntax difference) is that methods by default have context (this) set to refer to the object which they're part of. In this case inside of toString function this equals to str.
Note: Accessing a property (as in str.length) could in effect call a getter function but it depends on how the object is defined, and is in fact transparent for the user.

Why does [eval] work in [eval][0]('code')?

I saw this way to execute the code:
[eval][0]('alert("hello")')
I want to know what does unquoted 'eval' surrounded by square brackets mean and why this works. (For example, window['eval'][0]('alert("hello")') will lead to a TypeError). Is there any tutorials that describe such a syntax?
That is an indirect eval call
Quoting from the article:
According to ES5, all of these are indirect calls and should execute
code in global scope.
So you can use these kind of "tricks" to execute eval in the global scope instead of the current one.
It works before [eval] is an array where its 0-th element is the eval function, that is, [eval][0] === eval, and you are invoking it passing the string 'alert("hello")' as the argument.
The reason your example leads to a TypeError:
window['eval'][0]('alert("hello")')
is because you left out one set of brackets that would have made it equivalent:
[window['eval']][0]('alert("hello")')
The initial syntax you gave constructs an array with one element, the function eval. The 0th element of this array is therefore the eval function, which is immediately dereferenced using the square brackets.
Unquoted eval surrounded by brackets is an Array with one element which is eval.
[eval][0]('alert("hello")')
means take the first element of the Array [eval] and pass 'alert("hello")' to it. In other words,
eval('alert("hello")')
window['eval'][0]('alert("hello")')
on the otherhand tries to get the first element of window['eval'] which is not an Array, and thus the TypeError. window['eval'] is the same as eval unless there is another variable in scope called eval.
In Javascript
[x]
is a list of one element containing x. thus
[x][0]
is just a wordy and inefficient way of saying x.
Your example
[eval][0]('alert("hello")')
is therefore just like
eval('alert("hello")')
This kind of trickery is normally found in Javascript trojan or viruses, where the author tries to disguise what is happening.
Javascript however is full of special cases and when used with eval the code can also have the meaning of forcing global evaluation instead of local evaluation.
function defun(s) { [eval][0](s); }
function defun2(s) { eval(s); }
defun2("function square(x){return x*x}")
---> undefined
square(12)
---> ReferenceError: square is not defined
defun("function square(x){return x*x}")
---> undefined
square(12)
---> 144
See Matteo Tassinari answer link for details (note that the linked article is a bit dated, so ignore details about webkit behavior).

Why does JSHint dislike ternaries for method calls on objects?

JSHint give the following error:
Expected an assignment or function call and instead saw an expression.
For the following line of code:
(aFunctionOrNull) ? aFunctionOrNull() : someObject.someMethod();
It highlights the final ) on someMethod so I assume the error is there. The code works and JSHint doesn't have a problem when I change it to if () {} else {} syntax. I don't mind the longer syntax but I'd like to learn why JSHint says this and if this is a bad practice.
The biggest piece of confusion may come from the terminology. Is someObject.someMethod() not a function call?
Well, in general it's considered bad practice to call a function using the ternary operator(s), without assigning the return value (which is what you seem to be doing).Also, it could be worth checking what JSHint has to say about the following code:
(aFunctionOrNull || someObject.someMethod)();
If aFunctionOrNull is undefined (or null, or falsy), the logical-or-bit will cause the expression to evaluate to someObject.someMethod, and the resulting value of that is invoked (a reference to a function object, hopefully). This gives you the opportunity to write your code more "fail-safe" without the bulk of a nested ternary:
(aFunctionOrNull || someObject.someMethod || function(){})();
The grouped expression is now bound to evaluate to a truthy value, so no errors are thrown there.
To avoid JSHint nagging about your not doing anything with the return value, either assign it to a variable (which I don't really like doing), or add a little operator to the mix:
~(aFunctionOrNull || someObject.someMethod || function(){})();//bitwise not
!(aFunctionOrNull || someObject.someMethod || function(){})();//logical not, doesn't really matter which one
On your last question: someObject.someMethod is indeed a function call. More specifically, it's a call to a function object in the someObject's context.
For those who don't know this: JS functions are objects, and the called context is either explicitly set using the bind method (defined on the Function.prototype) or ad-hoc:
var referenceToMethod = someObject.someMethod;
referenceToMethod();//<-- inside the function objects, this now points to the global object
An easy way to think of it is that JS functions just float around aimlessly in memory/space/time, until they are called via a reference, the context of that reference is then passed to the function object, to determine what object it'll interact with. This is, sadly, the global object by default, or null in strict mode.
JSHint says about expressions, or expr:
This option suppresses warnings about the use of expressions where
normally you would expect to see assignments or function calls. Most
of the time, such code is a typo. However, it is not forbidden by the
spec and that's why this warning is optional.
While JSLint says:
An expression statement is expected to be an assignment or a
function/method call or delete. All other expression statements are
considered to be errors.
AFAIK, there's no problem in doing what you're doing only that it will issue a warning because it would expect you to use an if..else statement, but you can turn this off in JSHint with:
/*jshint expr:true */
There error is because a ternary is an expression. You could use it to set a variable:
var result = a ? b : c;
Notice that the ternary evaluates to either b or c. It's an expression.
That said, the warning (I believe) comes from the notion that ternaries suffer poorer readability than an if...else block. The code above can be rewritten
var result;
if (a) {
result = b;
} else {
result = c;
}
Which is easier to read than a ternary. JSHint does as much to promote readable code as it does valid code. If you're comfortable including these expressions in your code, go ahead and disable the warnings for expressions. (It's what I would do.)

Reference to Originating Conditional Value within a Javascript IF Statement

I often find that I write IF statements which immediately reference the value of the conditional statement. For example, let's say I need to check to see if a string matches a pattern:
if (mystring.match(/mypattern/) {
var mymatch = mystring.match(/mypattern/)[1];
...
};
I suspect that what I'm looking for doesn't exist, but I've wondered whether you can reference the conditional statement's value within the if block, the way you can reference "arguments" within a function. In many cases, of course, I can rewrite it like this:
var mymatch = mystring.match(/mypattern/)[1];
if (mymatch) { ... };
But that's often not possible if there's a series of methods called. For example:
var mymatch = $('.myclass')[0].text().match(/mypattern/)[1];
... that would throw an exception if there were no item [0] on which to call .text(). Is there some convenient shorthand I'm missing out on? Or a better way to organize things? Just curious, really — I'll go on living if the answer is no.
In cases where relevant you can use the fact that the assignment operator returns a value in JavaScript, so for instance you can write things like:
if (assignedTest = testedValue) {
//value of assignedTest is now available
//and conditional will only be executed if true
This could be used if the RHS was compatible or properly set-up but it's also a huge readability concern since it's very easy to confuse the assignment = with comparison ==/===.
If you were particularly motivated to pursue this you could extract this type of functionality into a function that would behave in a reliable way: such as assigning the result of a closure to a named variable, and you could further tune the behavior to do other things (such as optionally evaluating to a different value within the test). Ultimately it would primarily be making a simple structure more complex though.

JavaScript. An Odd Assignment Sentence

var test=(a=1,[b=2]["sort"])();
This code works in Firefox resulting test=window (window object),
Is it valid JavaScript code? (I failed to find it in JavaScript references)
It's "valid" but looks completely pathological to me. From the name of the var, I'd guess someone came up with this as a feature test at some point, but failed to add a comment explaining why.
So here's what it's doing. First, the two assignments will resolve to the assigned value, so we can replace them (they do assign variables, which is a side effect, but that doesn't affect the evaluation of this expression):
var test=(1, [2]["sort"])();
["sort"] is just .sort:
var test=(1, [2].sort)();
The comma operator will return the last value in the brackets, so we can lose that 1:
var test=([2].sort)();
So now the bracketed part is creating an array with the number 2 in it, and finding the sort method of that array. It then calls that method, but because of the first set of brackets it calls it without a specified context.
In non-strict mode, a function called with no context gets window as its this.
So it tries to sort window and returns the result, which is window, as you saw.
In strict mode, which the JS consoles in Firebug and Chrome are, functions called without context get undefined as their this, which means this example throws an error, as mplungjan noted above. https://developer.mozilla.org/en/JavaScript/Strict_mode
I would expect that code to give an error.
The comma basically evaluates the expression on the left, a=1 and then the expression on the right [b=2]["sort"] and returns the result of the expression on the right.
a=1 sets a to 1, creating a as a global if it's not in the current scope.
[b=2] sets b to 2, creating b as a global if it's not in the current scope, and also creates a one-element array with the value 2.
[b=2]["sort"] returns the array .sort method (it does not call the method).
So the result of the expression in parentheses is the array .sort method which is then executed by the final (), and the result would be assigned to test except that it doesn't work because by then it is not actually called on an array.
The final assignment is the equivalent of this: var test = ([2].sort)();.

Categories