Fun JavaScript: No curly braces. Argument: “the code will work just fine”


JavaScript is pretty in simple language for those who want to start learning it, but to achieve mastery in it, you need to put in a lot of effort.

Beginners often make a few common mistakes that come back to haunt them when they least expect it. To understand what these errors are, read this article.

1. Omitting curly braces

One of the mistakes that JavaScript beginners often make is skipping curly braces after statements like if, else, while, and for . Although this is not prohibited, you must be very careful because it may cause a hidden problem and lead to an error later.

See the example below:

JS

// This code doesn't do what it's supposed to do! if(name === undefined) console.log("Please enter a username!"); fail(); // Execution will never reach this line: success(name); ) function success(name)( console.log("Hello, " + name + "!"); ) function fail())( throw new Error("Name is missing. Can"t say hello!"); )

Although the fail() call is indented and appears to belong to an if statement, it does not. It is always called. So it's a good practice to surround all blocks of code with curly braces, even if they only contain one statement.

2. No semicolons

During JavaScript parsing, a process known as automatic placement semicolons. As the name suggests, the analyzer fills in the missing characters for you.

The purpose of this feature is to make JavaScript more accessible and easier to write for beginners. However, you should always add the semicolon yourself because there is a risk of missing it.

Here's an example:

JS

// The result of processing this code will be an error message. Adding a semicolon would solve the problem. console.log("Welcome the fellowship!") ["Frodo", "Gandalf", "Legolas", "Gimli"].forEach(function(name)( hello(name) )) function hello(name)( console. log("Hello, " + name + "!") )

Because there is no semicolon on line 3, the parser assumes that the opening parenthesis on line 5 is an attempt to access a property using array accessor syntax (see bug #8), rather than a separate array, which is not what it was supposed to be.

This results in an error. The fix is ​​simple - always insert a semicolon.

Some experienced JavaScript developers prefer not to use semicolons, but they are well aware of possible errors, and how to prevent them.

3. Misunderstanding of type casts

JavaScript supported dynamic types. This means that you don't have to specify the type when declaring a new variable, you can freely reassign or convert its value.

This makes JavaScript much simpler than, say, C# or Java. But this is fraught with the potential danger of errors, which in other languages ​​are detected at the compilation stage.

Here's an example:

JS

// Wait for an input event from a text box var textBox = document.querySelector("input"); textBox.addEventListener("input", function())( // textBox.value contains a string. Adding 10 contains // the string "10" but does not add it. console.log(textBox.value + " + 10 = " + (textBox.value + 10)); ));

HTML

The problem can be easily fixed by using parseInt(textBox.value, 10) to convert the string to a number before adding 10 to it.

Depending on how you use the variable, the runtime may decide that it should be converted to one type or another. This is called a type cast.

To prevent type conversion when comparing variables in an if statement, you can use strict equality check (=== ).

4. Forgotten var

Another mistake newbies make is they forget to use keyword var when declaring variables. JavaScript is a very liberal engine.

The first time it sees that you have used a variable without a var operator, it will automatically declare it globally. This may lead to some errors.

Here is an example that also illustrates another error - a missing comma when declaring several variables at once:

JS

var a = 1, b = 2, c = 3; function alphabet(str)( var a = "A", b = "B" // Oops, missing ","! c = "C", d = "D"; return str + " " + a + b + c + "…"; ) console.log(alphabet("Let"s say the alphabet!")); // Oh, no! Something's wrong! c has a new value! console.log(a, b, c);

When the parser reaches line 4, it will automatically add a semicolon and then interpret the c and d declarations on line 5 as global.

This will change the value of another variable c. More about JavaScript pitfalls here.

5. Floating point arithmetic

This error is typical for almost any programming language, including JavaScript. Because of the way that floating point numbers are represented in memory, arithmetic operations don't work quite the way you think.

For example:

JS

var a = 0.1, b = 0.2; // Surprise! This is wrong: console.log(a + b == 0.3); // Because 0.1 + 0.2 doesn't add up to what you expected: console.log("0.1 + 0.2 = ", a + b);

To work around this issue, you should not use decimal numbers, if you need absolute precision, use integers, or if you need to work with monetary units, use a library like bignumber.js.

6. Using constructors instead of original notation

When Java and C# programmers start writing JavaScript, they often prefer to create objects using constructors: new Array(), new Object(), new String().

JS

var elem4 = new Array(1,2,3,4); console.log("Four element array: " + elem4.length); // Create an array of one element. This doesn't work the way you think: var elem1 = new Array(23); console.log("One element array? " + elem1.length); /* String objects also have their own characteristics */ var str1 = new String("JavaScript"), str2 = "JavaScript"; // Strict equality is not observed: console.log("Is str1 the same as str2?", str1 === str2);

The solution to this problem is simple: try to always use literal originals
designations. Also, in JS it is not necessary to specify the size of arrays in advance.

7. Misunderstanding how ranges are divided

One of the hardest things for JS newbies to understand is the rules for delimiting and closing ranges. And it's really not easy:

JS

for(var i = 0; i< 10; i++){ setTimeout(function(){ console.log(i+1); }, 100*i); } /* Чтобы исправить проблему, заключите код в выражение самовыполняющейся функции: for(var i = 0; i < 10; i++){ (function(i){ setTimeout(function(){ console.log(i+1); }, 100*i); })(i); } */

Functions remain associated with variables within their parent ranges. But since we are delaying execution via setTimeout , when the time comes to run the functions, the loop will actually be completed and the i variable will be incremented to 11.

The self-executing function in the comments works because it copies the value of variable i and stores a copy of it for each delay in the function's execution. You can find out more about ranges here and here.

8. Using Eval

Eval is evil. This is considered bad practice and in most cases when you think of doing it, there is a better and faster way.

JS

// This is bad practice. Please don't do this: console.log(eval("obj.name + " is a " + obj." + access)); // Instead, use an annotations array to access properties dynamically: console.log(obj.name + " is a " + obj); /* Using eval in setTimout */ // This is also a bad practice. It is slow and difficult to test and debug: setTimeout(" if(obj.age == 30) console.log("This is eval-ed code, " + obj + "!");", 100); // It will be better this way: setTimeout(function())( if(obj.age == 30)( console.log("This code is not eval-ed, " + obj + "!"); ) ), 100);

The code inside eval is a string. The debugging messages associated with Eval blocks are confusing, and you'll have to rack your brain to get the single and double quotes right.

Not to mention that it will be slower than regular JavaScript. Don't use Eval unless you know exactly what you are doing.

9. Misunderstanding of asynchronous code

What really makes JavaScript stand out and make it unique is that almost everything works asynchronously and you have to pass callback functions in order to be notified of events.

It is still difficult for beginners to understand this intuitively, and they quickly reach a dead end when faced with errors that are difficult to understand.

Here's an example where I use the FreeGeoIP service to determine your location by IP address:

JS

// Define location data current user. load(); // Display the user's location. Oops, that doesn't work! Why? console.log("Hello! Your IP address is " + userData.ip + " and your country is " + userData.country_name); // The loaded function will determine the current user's ip and its location // via ajax, using the freegeoip service. When this is done it will place the returned // data into the userData variable. function load())( $.getJSON("http://freegeoip.net/json/?callback=?", function(response)( userData = response; // Output the following line from the comments to see the // result returned: // console.log(response); )); )

Even though console.log is located after the load() function is called, it is actually executed before the data is defined.

10. Abuse of event tracking

Let's assume that you want to track a button click, but only if the checker is installed.

Let's say I write

If(someVal) alert("True");

Then the next developer comes along and says, "Oh, I need to do something else," so they write

If(someVal) alert("True"); alert("AlsoTrue");

Now, as you can see, "AndTrue" will always be true because the original developer didn't use curly braces.

2018-12-04T00:00Z

Absolutely yes

Forget about "It's a personal preference", "the code will work fine", "it works fine for me", "it's more readable" yada yada BS.

Argument: "It's personal preference"

No. Unless you are the only person going to Mars, no. Most of the time there will be other people reading/modifying your code. In any serious coding team this would be the recommended way, so it's not a "personal preference".

Argument: “the code will work just fine”

So is the spaghetti code! Does this mean it's ok to create one?

Argument: “It works great for me”

In my career, I have seen so many bugs created because of this problem. You probably don't remember how many times you've commented out "DoSomething()" and are confused why "SomethingElse()" is called:

If (condition) DoSomething(); SomethingElse();

If (condition) DoSomething(); SomethingMore();

Here's an example real life. Someone wanted to enable all logging so they would run find & replace "Console.println" => //"Console.println" :

If (condition) Console.println("something"); SomethingElse();

See Problem?

Even if you think: “This is so trivial that I will never do it”; remember that there will always be a team member with lower programming skills than you (hopefully you're not the worst on the team!)

Argument: “it’s more readable”

If I've learned anything about programming, it's that it's very simple. It is very common that this is:

If (condition) DoSomething();

turns into the following after it has been tested with different browsers/ environments / use cases or new features added:

If (a != null) if (condition) DoSomething(); else DoSomethingElse(); DoSomethingMore(); else if (b == null) alert("error b"); else alert("error a");

And compare it to this:

If (a != null) ( if (condition) ( DoSomething(); ) else ( DoSomethingElse(); DoSomethingMore(); ) ) else if (b == null) ( alert("error b"); ) else ( alert("error a"); )

PS: Bonus points go to whoever spotted the error in the example above

2018-12-11T00:00Z

In addition to the reason mentioned by @Josh K (which also applies to Java, C, etc.), one of special problems in JavaScript is to automatically insert a semicolon. From an example on Wikipedia:

Return a + b; // Returns undefined. Treated as: // return; // a + b;

So it may also give unexpected results if used like this:

If (x) return a + b;

It's actually not much better to write

If (x) ( return a + b; )

but maybe the error here is a little easier to detect (?)

2018-12-18T00:00Z

The question asks about statements on one line. However, many examples give reasons not to leave curly braces across multiple lines. It's quite safe to not use parentheses on the same line if that's the coding style you prefer.

For example, the question asks if this is normal:

If (condition) statement;

He doesn't ask if everything is okay:

If (condition) statement;

I think leaving the parentheses is preferable because it makes the code more readable with less redundant syntax.

My coding style is to never use parentheses unless the code is a block. And never use multiple statements on the same line (separated by semicolons). I find it easy to read and clean up and never have problems with "if" statements. As a result, using parentheses in one if condition requires 3 lines. Like this:

If (condition) ( statement; )

Using a single line if statement is preferable because it uses less vertical space and the code is more compact.

I wouldn't force others to use this method, but it works for me and I couldn't disagree more with the examples given on how to exclude parentheses due to coding/scoping errors.

2018-12-25T00:00Z

No

This is absolutely true

If (cond) alert("Condition met!") else alert("Condition not met!")

This same practice is followed in all C syntax-style languages ​​with binding. C, C++, Java, even PHP all support single line operator without brackets. You must understand that you only save two characters, and with some styles, for some people, you don't even maintain the line. I prefer the full brace style (like the following), so it tends to be a little longer. The trade-off is met very well with the fact that you have very clear code readability.

If (cond) ( alert("Condition met!") ) else ( alert("Condition not met!") )

2019-01-01T00:00Z

First level The indentation of a statement must be equal to the number of open curly braces above it. (excluding quoted or commented braces or symbols in preprocessor directives)

Otherwise K&R would be a good indent. To correct their style, I recommend posting short simple operators if on one line.

I've always been surprised JavaScript First of all, it is probably like no other widely used language that simultaneously supports both paradigms: normal and abnormal programming. And if almost everything has been read about adequate best practices and templates, then the wonderful world of how you don’t have to write code, but can, remains only slightly ajar.


In this article we will analyze another far-fetched problem that requires unforgivable violation of a normal solution.


Previous task:

Formulation

Implement a decorator function that counts the number of calls to the passed function and provides the ability to retrieve that number on demand. In the decision forbidden use curly braces and global variables.

The call counter is just an excuse, because there is console.count() . The point is that our function accumulates some data when calling the wrapped function and provides some kind of interface for accessing it. This could be saving all the results of the call, collecting logs, or some kind of memoization. It’s just that the counter is primitive and understandable to everyone.


The whole difficulty lies in the abnormal limitation. You cannot use curly braces, which means you will have to reconsider everyday practices and ordinary syntax.

The usual solution

First you need to choose a starting point. Typically, if the language or its extension does not provide required function decoration, we implement a certain container ourselves: a wrapped function, accumulated data and an interface for accessing it. Often this is the class:


class CountFunction ( constructor(f) ( this.calls = 0; this.f = f; ) invoke() ( this.calls += 1; return this.f(...arguments); ) ) const csum = new CountFunction ((x, y) => x + y); csum.invoke(3, 7); // 10 csum.invoke(9, 6); // 15 csum.calls; // 2

This is not immediately suitable for us, because:

  1. In JavaScript, you cannot implement a private property this way: we can either read calls instance (which is what we need), and write a value into it from the outside (which we do NOT need). Of course, we can use a closure in the constructor, but then what is the point of the class? I would still be wary of using fresh private fields without babel 7.
  2. The language supports a functional paradigm, and instantiation via new it seems not here the best solution. It's nicer to write a function that returns another function. Yes!
  3. Finally, the syntax ClassDeclaration And MethodDefinition will not allow us, no matter how much we want, to get rid of all the curly braces.

But we have a great one that implements privacy using a closure:


function count(f) ( let calls = 0; return ( invoke: function() ( calls += 1; return f(...arguments); ), getCalls: function() ( return calls; ) ); ) const csum = count((x, y) => x + y); csum.invoke(3, 7); // 10 csum.invoke(9, 6); // 15 csum.getCalls(); // 2

You can already work with this.

Interesting solution

What are curly braces used for here anyway? These are 4 different cases:

  1. Defining the body of the function count ( FunctionDeclaration)
  2. Initializing the returned object
  3. Defining the body of the function invoke ( FunctionExpression) with two expressions
  4. Defining the function body getCalls( FunctionExpression) with one expression

Let's start with second point. We don't really need to return a new object while making it difficult to call the final function via invoke. We can take advantage of the fact that a function in JavaScript is an object, which means it can contain its own custom fields and methods. Let's create our return function df and add a method to it getCalls, which through the closure will have access to calls as before:


function count(f) ( let calls = 0; function df() ( calls += 1; return f(...arguments); ) df.getCalls = function() ( return calls; ) return df; )

It’s more pleasant to work with this:


const csum = count((x, y) => x + y); csum(3, 7); // 10 csum(9, 6); // 15 csum.getCalls(); // 2

C fourth everything is clear: we will simply replace FunctionExpression on ArrowFunction. The absence of curly braces will be ensured by a short notation of the arrow function in the case of a single expression in its body:


function count(f) ( let calls = 0; function df() ( calls += 1; return f(...arguments); ) df.getCalls = () => calls; return df; )

WITH third- everything is more complicated. We remember that the first thing we did was replace FunctionExpression functions invoke on FunctionDeclaration df. To rewrite this to ArrowFunction you will have to solve two problems: not to lose access to the arguments (currently this is a pseudo-array arguments) and avoid the function body of two expressions.


The parameter explicitly specified for the function will help us deal with the first problem args with spread operator. And to combine two expressions into one, you can use logical AND. Unlike the classic logical conjunction operator, which returns a Boolean, it evaluates the operands from left to right up to the first “false” and returns it, and if all are “true”, then the last value. The very first increment of the counter will give us 1, which means this sub-expression will always be reduced to true. We are not interested in reducing the result of the function call in the second sub-expression to “truth”: the evaluator will stop at it in any case. Now we can use ArrowFunction:


function count(f) ( let calls = 0; let df = (...args) => (calls += 1) && f(...args); df.getCalls = () => calls; return df; )

You can decorate the recording a little using prefix increment:


function count(f) ( let calls = 0; let df = (...args) => ++calls && f(...args); df.getCalls = () => calls; return df; )

Solution first and let's start with the most difficult point with replacement FunctionDeclaration on ArrowFunction. But for now we will still have the body in curly braces:


const count = f => ( let calls = 0; let df = (...args) => ++calls && f(...args); df.getCalls = () => calls; return df; );

If we want to get rid of the curly braces surrounding the body of the function, we will have to avoid declaring and initializing variables through let. And we have two variables: calls And df.


First, let's deal with the counter. We can create a local variable by defining it in the function parameter list, and pass the initial value by calling it using IIFE (Immediately Invoked Function Expression):


const count = f => (calls => ( let df = (...args) => ++calls && f(...args); df.getCalls = () => calls; return df; ))( 0);

All that remains is to concatenate three expressions into one. Since all three expressions are functions that always evaluate to true, we can also use logical AND:


const count = f => (calls => (df = (...args) => ++calls && f(...args)) && (df.getCalls = () => calls) && df)(0 );

But there is another option for concatenating expressions: using comma operator. It is preferable because it does not involve unnecessary logical transformations and requires fewer parentheses. The operands are evaluated from left to right, and the result is the value of the latter:


const count = f => (calls => (df = (...args) => ++calls && f(...args), df.getCalls = () => calls, df))(0);

Perhaps I managed to deceive you? We safely got rid of the variable declaration df and left only the assignment to our arrow function. In this case, this variable will be declared globally, which is unacceptable! Let's repeat for df initializing a local variable in the parameters of our IIFE function, but we will not pass any initial value:


const count = f => ((calls, df) => (df = (...args) => ++calls && f(...args), df.getCalls = () => calls, df)) (0);

Thus the goal has been achieved.

Variations on a theme

Interestingly, we were able to avoid creating and initializing local variables, multiple expressions in function blocks, and creating an object literal. At the same time, the purity of the original solution was preserved: the absence of global variables, the privacy of the counter, access to the arguments of the wrapped function.


In general, you can take any implementation and try to do something similar. For example, a polyfill for a function bind in this regard it is quite simple:


const bind = (f, ctx, ...a) => (...args) => f.apply(ctx, a.concat(args));

However, if the argument f is not a function, in a good way we should throw an exception. And the exception throw cannot be thrown away in the context of an expression. You can wait for throw expressions (stage 2) and try again. Or does anyone already have thoughts?


Or consider a class that describes the coordinates of a certain point:


class Point ( constructor(x, y) ( this.x = x; this.y = y; ) toString() ( return `($(this.x), $(this.y))`; ) )

Which can be represented by a function:


const point = (x, y) => (p => (p.x = x, p.y = y, p.toString = () => ["(", x, ", ", y, ")"].join (""), p))(new Object);

Only here we have lost prototypical inheritance: toString is a property of the prototype object Point, rather than a separately created object. Can this be avoided if we try hard enough?


As a result of the transformations, we get an unhealthy mixture of functional programming with imperative hacks and some features of the language itself. If you think about it, this could make an interesting (but not practical) obfuscator source code. You can come up with your own version of the “bracket obfuscator” problem and entertain colleagues and friends of JavaScripters in your free time. useful work time.

Conclusion

The question is, who is this useful for and why is it needed? This is completely harmful for beginners, as it creates a false impression of the excessive complexity and deviance of the language. But it can be useful for practitioners, as it allows you to look at the features of the language from the other side: a call not to avoid, but a call to try in order to avoid in the future.

Tags: Add tags

Errors in the program are quite difficult to find. And to make your task easier, you need to write the code correctly and beautifully (readable). Good code should be: readable, consistent, predictable, well-formatted, and it should also have documentation.

Important points regarding code formatting

Indentations

If you don't indent the code, it's impossible to read. Typically, indentations are made with a tab character, but there are also those who indent using spaces, usually 3-4 spaces. Below is an example of correct and incorrect indentation:

/* Correct indentation */

< max; i++) {
if (arr[i] % 2 === 0) (
answer = (
sum: sum += arr[i]
};
}
}
/* And here everything is bad */
var answer, arr = , sum = 0;
for (var i = 0, max = arr.length; i< max; i++) {
if (arr[i] % 2 === 0) (
answer = (
sum: sum += arr[i]
};
}
}

Braces

Always use curly braces, even if they are not needed. From a technical point of view, if the body of an if, while or for construct consists of a single statement, then the curly braces can be omitted. Having curly braces always written makes it easier to make changes later. Below is an example of how to do it right and what not:

/* Correct entry */
for (var i = 0; i< 5; i++) {
alert(i);
}
/* But there isn’t one */
for (var i = 0; i< 5; i++)
alert(i);

Location of the opening brace

There are two types of programmers:

If (a > b) (
...
}
if (a > b)
{
...
}

How to write an opening curly brace is up to you. We already know that JavaScript itself inserts semicolons and here the problem arises in the second method. Let's say you write this piece of code:

Return
{
id: 1
};

And what will the interpreter do? He inserts a semicolon after return and it turns out that the function will return undefined . That is, the interpreter sees this piece of code like this:

Return undefined;
{
id: 1
};

Spaces

Spaces must be used correctly. When you write on paper, you leave a comma after empty space? I guess it's yes. And when listing anything in JavaScript, you need to put a space after the comma. Where should I put a space to make the code clear?

1. After semicolons in the for statement

For (var i = 0; i< 100; i++) {...}

2. When declaring multiple variables in a for statement

For (var i = 0, max = arr.length; i< max; i++) {...}

3. After commas, between array elements

The third part of the lesson on JavaScript code. Simple guidelines for creating an easily maintainable project.

Avoid implied type conversions

JavaScript involves converting variable types when comparing them. Therefore, comparisons such as false == 0 or "" == 0 return true .

To avoid problems caused by implied type conversion, always use the === and !== operators to check both the values ​​and types of the expressions being compared:

There is another school of programming that considers it overuse of the === operator when the == operator is sufficient. For example, when using typeof, which returns a string, there is no reason to require strict matching. But JSLint requires strict conformance. And, in addition, the code will look more coherent and reduce the amount of thinking when reading (" This operator== used intentionally or by mistake?").

Avoid using eval()

The eval() function takes an arbitrary string and executes it as JavaScript code. If the code is known (and not determined during process execution), there is no reason to use eval() at all. If the code is dynamically generated at runtime, then it is often possible to achieve the goal the best method, how using eval(). For example, using square bracket notation to access properties dynamically is better and simpler:

// bad var property = "name"; alert(eval("obj." + property)); // preferable to do this var property = "name"; alert(obj);

Using eval() can also have security implications, as you may be executing code (for example, obtained from the network) that is harmful. A fairly common bad practice when working with a JSON response to an AJAX request. IN in this case It's better to use the browser's built-in methods to parse the JSON response to solve the problem safe method and rightly so. For browsers that do not support JSON.parse(), you can use the library from JSON.org.

It's also important to remember that passing strings to setInterval() , setTimeout() , and the Function() constructor is similar to using eval() in most cases. Therefore, such actions should be avoided. In the background JavaScript evaluates and executes the strings you pass in like program code:

// bad setTimeout("myFunc()", 1000); setTimeout("myFunc(1, 2, 3)", 1000); //preferably setTimeout(myFunc, 1000); setTimeout(function () ( myFunc(1, 2, 3); ), 1000);

Using the new Function() constructor is similar to eval() and should be used with caution. This powerful tool, but often used incorrectly. If you absolutely must use eval() , consider using new Function() instead. There is a small potential benefit in that the code defined in new Function() will run in the function's local space, so variables defined with a var directive in the code defined will not automatically become global. Another way to avoid automatic detection global variables - wrap the eval() call in a function.

Consider the following example. Here only un remains as a global variable, polluting the namespace:

Console.log(typeof un); // "undefined" console.log(typeof deux); // "undefined" console.log(typeof trois); // "undefined" var jsstring = "var un = 1; console.log(un);"; eval(jsstring); // Logs "1" jsstring = "var deux = 2; console.log(deux);"; new Function(jsstring)(); // Logs "2" jsstring = "var trois = 3; console.log(trois);"; (function () ( eval(jsstring); )()); // Logs "3" console.log(typeof un); // number console.log(typeof deux); // undefined console.log(typeof trois); // undefined

Another difference between eval() and the new Function() constructor is that eval() can overlap the namespace chain, while Function execution occurs in a sandbox. It doesn't matter where you execute Function , it only uses the global namespace. Therefore, it pollutes the local namespace less. IN following example eval() can access and modify variables in its external namespace, but Function cannot (the usage of Function and new Function is identical):

(function () ( var local = 1; eval("local = 3; console.log(local)"); // Logs "3" console.log(local); // Logs "3" )()); (function () ( var local = 1; Function("console.log(typeof local);")(); // Logs "undefined" )());

Converting a number using parseInt()

Using parseInt() you can get a number from a string. The function takes a second parameter - the base of the number system, which is often omitted. But in vain. The problem occurs when you need to parse a string that starts with 0: for example, part of a date that is entered into a form field. A string that starts with 0 is treated as octal number(radix 8), which was defined in ECMAScript 3 (but changed in ECMAScript 5). To avoid incompatibilities and unexpected results, you should always use the radix parameter:

Var month = "06", year = "09"; month = parseInt(month, 10); year = parseInt(year, 10);

IN in this example, if you omit the radix parameter (call the function as parseInt(year)), you will get the value 0 because “09” is implied to be an octal number (as if you called parseInt(year, 8)) and 09 is incorrect number in base 8.

Alternative Methods converting a string to a number:

+"08" // result 8 Number("08") // 8

These methods are often faster than parseInt() because parseInt() does string parsing rather than simple conversion. But if you assume the input might be in the form “08 hello”, then parseInt() will return a number and the other methods will fail and return NaN .

Code requirements

It is important to draw up code requirements and follow them - such a step will make the code consistent, predictable and significantly easier and understandable. A new developer on your team following code requirements is essential will go in faster into the working rhythm, perceiving the code written by other project participants.

Serious clashes and showdowns arise when discussing various aspects code requirements (for example, whether to indent with spaces or tabs). Therefore, when introducing code requirements, you need to seriously prepare for discussions. But the code requirements and strict adherence to them are very important for the existence and successful development of the project.

Indentations

Some developers prefer using tabs for indentation, since everyone can configure their editor to output a certain number of spaces instead of tabs according to their preferences. Others prefer to use spaces. For the essence of the issue, this is not important, the main thing is that indentations are defined in the current code requirements.

Where should the indentations be made? The rule is simple - wherever there are curly braces. That is, in the body of functions, loops (do, while, for, for-in), if and switch statements, and object properties. The following code shows examples of using indentation:

Function outer(a, b) ( var c = 1, d = 2, inner; if (a > b) ( inner = function () ( return ( r: c - d ); ) ) else ( inner = function ( ) ( return ( r: c + d ); ) return inner; )

Braces

Curly braces should always be used, even in cases where they are options. Technically, when you only have one expression in an if or for statement, curly braces are not required, but they should be used anyway. They make the code more consistent and easier to extend.

Let's imagine that you have a loop with one expression. You can omit the parentheses, which won't happen syntax error:

// bad for (var i = 0; i< 10; i += 1) alert(i);

But what if you later need to add another line to the body of the loop?

// bad for (var i = 0; i< 10; i += 1) alert(i); alert(i + " is " + (i % 2 ? "odd" : "even"));

The second alert function is outside the loop, and indentation can play a bad joke on you. It's best for the future to always use parentheses, even for a single-line block:

// preferably for (var i = 0; i< 10; i += 1) { alert(i); }

Also for the conditions:

// bad if (true) alert(1); else alert(2); // preferably if (true) ( ​​alert(1); ) else ( alert(2); )

Open bracket position

The question often arises: where should the open parenthesis be placed - on the same line or on the next one?

If (true) ( ​​alert("Message!"); )

If (true) ( ​​alert("Message"); )

In this example, the position of the bracket is a matter of preference. But there are cases where the program will behave differently depending on the position of the bracket. This situation occurs because of the semicolon insertion mechanism - JavaScript doesn't understand when you choose not to end the line correctly, and will add the semicolon for you. This behavior can cause problems when the function returns a literal object and the open parenthesis is at next line:

// warning: unexpected return function func() ( return // follows a block of code that will never be executed ( name: "Batman" ) )

If you expected this function to return an object with the name property, you will be unpleasantly surprised. Because of the implied semicolon, the function will return undefined . The previous code is equivalent next block:

// warning: unexpected return function func() ( return undefined; // follows a block of code that will never execute ( name: "Batman" ) )

Function func() ( return ( name: "Batman" ); )

Note the semicolon. Just like curly braces, you should always use a semicolon, even when it is implied by the construct JavaScript code. Not only does this create discipline and align with a more rigorous approach to coding, but it also helps avoid ambiguous situations like the example above.







2024 gtavrl.ru.