Once, I saw an example like this:
var a, x, y;
var r = 10;
with (Math) {
a = PI * r * r;
x = r * cos(PI);
y = r * sin(PI / 2);
}
And it looks very convenience, because that way I don't have to type all the Math.s.
But when I take a look at the MDN, it says:
Using with is not recommended, and is forbidden in ECMAScript 5 strict mode. The recommended alternative is to assign the object whose properties you want to access to a temporary variable.
So is it okay to use with()? In HTML5?
The MDN you linked says Using with is not recommended...
with is an excellent way of making spaghetti code for lunch.
You might like it, but the guy that will need to debug it will curse you.
javascript has some very weird operators, like the comma operator(,).
Can you understand what the following code does?
var a = "a";
var b = "b";
a = [b][b = a,0];
Well it swaps a and b... You don't understand , so as the guy that will need maintain your with code. Don't use hacks, hacks are cool in charades games, not in real code.
When is the comma operator useful?
The comma swap Fiddle
It is okay to use any feature of JavaScript, so long as you understand it.
For example, using with you can access existing properties of an object, but you cannot create new ones.
Observe:
var obj = {a:1,b:2};
with(obj) {
a = 3;
c = 5;
}
// obj is now {a:3,b:2}, and there is a global variable c with the value 5
It can be useful for shortening code, such as:
with(elem.parentNode.children[elem.parentNode.children.length-3].lastChild.style) {
backgroundColor = "red";
color = "white";
fontWeight = "bold";
}
Because the properties of the style object already exist.
I hope this explanation is clear enough.
In his excellent book "Javascript: The Good Parts", Douglas Crockford lists the "with Statement" in Appendix B: The Bad Parts.
He says "Unfortunately its results can sometimes be unpredictable, so it should be avoided".
He goes on to give an example, where an assignment inside the with will operate on different variables depending on whether the object is defined or not.
See With statement considered harmful (but less detailed than the explanation in the book).
Related
Begin:
The Math object in JavaScript can prove to be extremely useful. In a page using the Math object repeatedly, I would rather not continuously use. I would prefer to use these functions at top-level. I will provide an example on how this is possible:
The With Keyword (Bad Way):
Let me state the following: This is absolutely terrible, never use it.
with(Math) {
let q = min(10,211);
let r = max(2,8);
let e = random();
let p = floor(e*r)
console.log(q*r/e)
}
Bringing an Object to Front By Defining It As Such (Good Way):
I enjoy using this way much more than the way above.
let {min,max,random,floor} = Math;
let q = min(10,211);
let r = max(2,8);
let e = random();
let p = floor(e*r);
console.log(q*r/e);
Continuation:
I am asking if anyone knows of a way to accomplish what the with keyword does without with because I find with terrible. I am curious to know if it is possible to get all of the words of Math and store it into an Object that is defined as Math. I understand that this may be confusing. Thank you for reading.
For ordinary objects (instances of the Object class) you could use Object.assign to add their properties to the window object. But for Math and the other base objects their properties seem not to be enumerable. Instead, following this answer you can use Object.getOwnPropertyNames to find all the properties of Math and attach them to the window object.
for (let prop of Object.getOwnPropertyNames(Math)) {
window[prop] = Math[prop];
}
console.log(PI); // 3.14...
I would suggest this is not a great practice as it is not very transparent about what names are being added to the global namespace.
This question already has answers here:
What does the construct x = x || y mean?
(12 answers)
Closed 6 years ago.
In JavaScript I recently realized you could use the OR || logical operator for assignment, and I want to know if it's considered bad practice.
In particular I have some functions that have optional array input, if the input is null or undefined I should just set it to an empty array [], if it has content it should take the content.
I found that using the assignment using the OR operator handles that perfectly in a single line, it's clean. However, it feels like the kind of thing that might be considered bad practice, or may have some horrible pitfalls I'm not considering.
Another approach is a simple if check, which is fairly safe in general.
I want to know if using the || approach seen below has any pitfalls I'm not considering, although it works in this scenario I would appreciate knowing if it works well to keep using this in the future, or to stop using it altogether.
https://jsbin.com/nozuxiwawa/1/edit?js,console
var myArray = ['Some', 'Strings', 'Whatever'];
// Just assign using OR
var pathOne = function(maybeAnArray) {
var array = maybeAnArray || [];
console.log(array);
}
// Assign using IF
var pathTwo = function(maybeAnArray) {
var array = [];
// Covers null and undefined
if (maybeAnArray != null) {
array = maybeAnArray;
}
console.log(array);
}
console.log('Path one:');
pathOne(myArray); // ['Some', 'Strings', 'Whatever']
pathOne(null); // []
console.log('\nPath two:');
pathTwo(myArray); // ['Some', 'Strings', 'Whatever']
pathTwo(null); // []
IMHO the use of the OR || for the purposes of assignment is perfectly valid and is good practice. We certainly use it in our projects and I've seen it used in lots of 3rd party projects that we use.
The thing you need to be aware of is how certain JavaScript objects can be coerced to be other values. So for example, if you're ORing values such as "", false or 0 then they are treated as false... this means that when you have the following:
function f(o) {
var x = o || -1;
return x;
}
Calling:
f(0)
...will return -1... but calling
f(1)
Will return 1 ... even though in both cases you passed a number - because 0 is treated as false -1 is assigned to x.
...that said, as long as you're aware of how the OR operator will treat the operands that you use with it - then it is good JavaScript practice to use it.
i prefer the first option, it's clear for my eyes, but when i need to share my code with others will think about to use second, will be more clear for any.
Now i'm using sonar, and prefer the second option too, will more easy to comprend for machine in inegration works.
Last idea is to use
if(maybeAnArray !== void(0))
Two reasons:
use cast and type conditionals
void(0) will works same for all browsers
Expect it helps yopu
When given the option, I prefer concise code (which must still be readable).
I would say || is common enough that it is considered good practice. Once one has seen it a few times it reads just fine.
In my opinion there are few reasons why you should rather use the second option:
First of all it's much more readable - new developers that are still learning can have problems with understanding notation like var myArray = someArrayArg || [];
If you are using some kind of code checkers like JSLint, they will return warnings and/or errors like Expected a conditional expression and instead saw an assignment. for the statement with var myArray = someArrayArg || [];
We already have something like var myArray = someArrayArg ? someArrayArg : []; that works pretty well
I don't know how to describe this, but this doesn't error out in Javascript... but it doesn't mean its a good idea and that all versions of Javascript except it (or not).
Thoughts?
var r = 'r';
var t = 't';
var s = 's';
s = r = t;
// s = 't'
// r = 't'
// t = 't'
It doesn't seem standard and it may be harder for a developer to follow, but are there really any use cases for this?
This works because the assignment of r=t returns the assigned value. So yes you can infinitely assign values based on return values.
It is a fairly standard practice to chain assignments together. It even has a name called "chain assignment". I don't know where you get the idea of "this is bad coding" from, but this is definitely a normal thing to see. This works because assignments return the assigned value.
This is commonly used for initializing variables:
var a, b, c;
a = b = c = 5; //one use case
//same as
a = (b = (c = 5)));
It doesn't seem standard and it may be harder for a developer to follow.
If a developer cannot understand this expression, I don't know what to say.
I use it all the time in my modules to create a local shortcut to functions (for use within the module):
var doSomething = module.exports.doSomething = ()=>{};
It's nice the way javascript returns values. In languages like python you have to do this sort of thing way to often:
def do_something(ctx):
ctx.update({
'entry': entry,
'section': 'select_category'
})
do_something_else(ctx)
instead of
def do_something(ctx):
do_something_else(ctx.update({
'entry': entry,
'section': 'select_category'
})
because the update method doesn't return anything.
I'm sure this thing is duplicated somewhere but I don't know what to search.
So, I've been looking through a Node.JS Application and found this code and wondered what it does. I have tried searching but I don't know what to search so I was hoping someone would it explain it to me.
init = refresh = function () {
// code here..
};
I understand 1 equals, but why 2? does it make some sort of alias so that function can be run with both init and refresh?
= resolves the right hand side and then assigns the result to the left hand side.
The result of doing this is the same as the result assigned.
So that assigns the function to both init and refresh
Quentin did a very good job telling you what it is doing.
I just wanted to chime in to give an example where you might use this:
Say for instance you have an object:
var obj = {
init: function() {
var x = this.x = [1,2,3];
}
};
What this allows you to do is reference your x variable two different ways (either through x or this.x).
Now why would you do this?
Well two major reasons.
It is faster to access x rather than this.x (but you still need to access it elsewhere)
It produces easier to read code when having to read/write to x lots of times in one function.
This is just another reason why you would use it.
But in most cases it is just aliases, such as: forEach -> each
Here's an explanation using operator associativity and precedence.
So, looking at an operator precedence description from Mozilla, when an expression includes multiple operators of the same precedence, as in
a OP b OP c
, then you check whether that level of precedence uses right-to-left or left-to-right associativity.
a = b = c
The assignment operator in JavaScript is the only operator on its level of precedence.
It has right-to-left associativity
So in a = b = c, b = c is evaluated first, assigning the value of c to b.
Then the expression becomes a = b.
a="12345"
a[2]=3
a[2]='9'
console.log(a) //=> "12345"
What is going on?? This quirk caused me 1 hour painful debugging. How to avoid this in a sensible way?
You cannot use brackets to rewrite individual characters of the string; only 'getter' (i.e. read) access is available. Quoting the doc (MDN):
For character access using bracket notation, attempting to delete or
assign a value to these properties will not succeed. The properties
involved are neither writable nor configurable.
That's for "what's going on" part of the question. And for "how to replace" part there's a useful snippet (taken from an answer written long, long ago):
String.prototype.replaceAt = function(index, char) {
return this.slice(0, index) + char + this.slice(index+char.length);
}
You may use as it is (biting the bullet of extending the JS native object) - or inject this code as a method in some utility object (obviously it should be rewritten a bit, taking the source string as its first param and working with it instead of this).
According to this question, this is not supported among all browsers.
If your strings aren't too long, you can do this relatively easy like that:
var a="12345";
a = a.split("");
a[2]='9';
a = a.join("");
console.log(a);
var letters = a.split('');
letters[2] = 3;
letters[2] = 9;
console.log(letters.join(''));
http://jsfiddle.net/XWwKz/
Cheers