Bài viết này cung cấp một vài đặc điểm cơ bản của ngôn ngữ lập trình JavaScript, rất phù hợp với người mới bắt đầu làm quen với ngôn ngữ này. Đi kèm bài viết này là nhiều ví dụ mẫu JavaScript giúp người đọc thực hành JavaScript tốt hơn, cùng với những giải thích rất chi tiết.
- Demo
- Phóng to
- Tải lại
- Cửa sổ mới
Miễn phí web hosting 1 năm đầu tại iPage
Nếu bạn vẫn còn đang tìm kiếm một nhà cung cấp hosting đáng tin cậy, tại sao không dành chút thời gian để thử với iPage, chỉ với không quá 40.000 VNĐ/tháng, nhưng bạn sẽ được khuyến mãi kèm với quà tặng trị giá trên 10.000.0000 VNĐ nếu thanh toán cho 24 tháng ~ 900.000 VNĐ?
Có trên 1 triệu khách hàng hiện tại của iPage đã & đang hài lòng với dịch vụ, tuyệt đối chắc chắn bạn cũng sẽ hài lòng giống họ! Quan trọng hơn, khi đăng ký sử dụng web hosting tại iPage thông qua sự giới thiệu của chúng tôi, bạn sẽ được hoàn trả lại toàn bộ số tiền bạn đã sử dụng để mua web hosting tại iPage. Wow, thật tuyệt vời! Bạn không phải tốn bất kì chi phí nào mà vẫn có thể sử dụng miễn phí web hosting chất lượng cao tại iPage trong 12 tháng đầu tiên. Chỉ cần nói chúng tôi biết tài khoản của bạn sau khi đăng ký.
Nếu muốn tìm hiểu thêm về ưu / nhược điểm của iPage, bạn hãy đọc đánh giá của ChọnHostViệt.com nhé!
---
Use === to Test Equality
When testing equality, a lot of languages with syntax similar to JavaScript use the double equals operator (==). However, in JavaScript you should always use triple equals (===). The difference is in how equality is determined. A triple equals operator evaluates the two items based upon their type and value. It makes no interpretations. Let's look at a couple examples:
if(1 === '1') //Returns false
if(1 == '1') //Returns true
if(0 === '') //Returns false
if(0 == '') //Returns true
The first line would equal false because the number one does not equal the character 1. That is what we would expect. The double equals operator, on the other hand, will attempt to coerce the two values to be the same type before comparing equality. This can lead to unexpected results. In the second grouping, the result using the double equals would be true. That probably isn't what we were expecting.
Just to be clear here, the same rule applies to the inequality operator as well. Looking at our above tests, we can see that both types of inequality operators work the same way as their counterparts:
if(1 !== '1') //Returns true
if(1 != '1') //Returns false
if(0 !== '') //Returns true
if(0 != '') //Returns false
The bottom line here is that we should always use the triple equals operator (or !== for not equal) rather than the double equals. The results are far more expected and predictable. The only exception would be once you are positive you understand what is happening and you absolutely need the coercion before comparison.
Include All Necessary Semicolons
Most JavaScript developers won't intentionally fail to put semicolons in the proper places. However, you need to be aware that the browser will usually put in semicolons where it thinks they are necessary. This can enable a bad habit that will come back to bite you down the road. In some instances, the compiler might assume that a semicolon is not needed, which will introduce tricky, hard-to-find bugs into your code. Avoid this by always adding the proper semicolons. A good tool to help you check your JavaScript for forgotten semicolons is JSLint.
Use JSLint
As I mentioned above, JSLint is a great tool for helping you identify common problems in your JavaScript code. You can paste your code into the website listed above, you can use a different site like JavaScriptLint.com, or you can use one of the many downloadable JSLint tools. For instance, Visual Studio has an add-in for JSLint that will allow you to check for errors at compile-time (or manually).
Whatever you choose to do, the key point here is to run a tool like JSLint on your code. It will pick up bad code that is being masked by the browser. This will make your code cleaner and it will help to prevent those pesky bugs from showing up in production.
Use a Namespace
When you first start using JavaScript, the temptation is to just declare everything and use it as needed. This places all of your functions and variables into the global scope. The problem with this, besides it being sloppy, is that it makes your code extremely vulnerable to being affected by other code. For instance, consider the following example:
var cost = 5;
//...time goes by...
console.log(cost);
Imagine your surprise when the alert pops up and says "expensive" instead of 5. When you trace it down, you might find that a different piece of JavaScript somewhere else used a variable called cost to store text about cost for a different section of your application.
The solution to this is namespacing. To create a namespace, you simply declare a variable and then attach the properties and methods you want to it. The above code would be improved to look like this:
var MyNamespace = {};
MyNamespace.cost = 5;
//...time goes by...
console.log(MyNamespace.cost);
The resulting value would be 5, as expected. Now you only have one variable directly attached to the global context. The only way you should have a problem with naming conflicts now is if another application uses the same namespace as you. This problem will be much easier to diagnose, since none of your JavaScript code will work (all of your methods and properties will be wiped out).
Avoid Using Eval
The Eval function allows us to pass a string to the JavaScript compiler and have it execute as JavaScript. In simple terms, anything you pass in at runtime gets executed as if it were added at design time. Here is an example of what that might look like:
eval("alert('Hi');");
This would pop up an alert box with the message "Hi" in it. The text inside the eval could have been passed in by the user or it could have been pulled from a database or other location.
There are a couple reasons why the eval function should be avoided. First, it is significantly slower than design time code. Second, it is a security risk. When code is acquired and executed at runtime, it opens a potential threat vector for malicious programmers to exploit. Bottom line here is that this function should be avoided at all costs.
Use Decimals Cautiously
When is 0.1 + 0.2 not equal to 0.3? When you do the calculation in JavaScript. The actual value of 0.1 + 0.2 comes out to be something like 0.30000000000000004. The reason for this (nope, not a bug) is because JavaScript uses Binary Floating Point numbers. To get around this issue, you can multiply your numbers to remove the decimal portion. For instance, if you were to be adding up the cost of two items, you could multiply each price by 100 and then divide the sum by 100. Here is an example:
var hamburger = 8.20;
var fries = 2.10;
var total = hamburger + fries;
console.log(total); //Outputs 10.299999999999999
hamburger = hamburger * 100;
fries = fries * 100;
total = hamburger + fries;
total = total / 100;
console.log(total); //Outputs 10.3
Start Blocks on the Same Line
Most developers that write software in other C-family programming languages use the Allman style of formatting for block quotes. This places the opening curly brace on its own line. This pattern would look like this in JavaScript:
if(myState === 'testing')
{
console.log('You are in testing');
}
else
{
console.log('You are in production');
}
This will work most of the time. However, JavaScript is designed in such a way that following the K&R style of formatting for blocks is a better idea. This format starts the opening curly brace on the same line as the preceding line of code. It looks like this:
if(myState === 'testing') {
console.log('You are in testing');
} else {
console.log('You are in production');
}
While this may only seem like a stylistic difference, there can be times when there is a impact on your code if you use the Allman style. Earlier we talked about the browser inserting semicolons where it felt they were needed. One fairly serious issue with this is on return statements. Let's look at an example:
return
{
age: 15,
name: Jon
}
You would assume that the object would be returned but instead the return value will be undefined
.
The reason for this is because the browser has inserted a semicolon
after the word return, assuming that one is missing. While return is
probably the most common place where you will experience this issue, it
isn't the only place. Browsers will add semi-colons after a number of
keywords, including var and throw.
It is because of this type of issue that is is considered best practice to always use the K&R style for blocks to ensure that your code always works as expected.
Use Explicit Blocks
There are a number of shortcuts and one-liners that can be used in lieu of their explicit counterparts. In most cases, these shortcuts actually encourage errors in the future. For instance, this is acceptable notation:
if (i > 3)
doSomething();
The problem with this is what could happen in the future. Say, for instance, a programmer were told to reset the value of i
once the doSomething()
function was executed. The programmer might modify the above code like so:
if (i > 3)
doSomething();
i = 0;
In this instance, i
will be reset to zero even if the if
statement evaluates to false. The problem might not be apparent at
first and this issue doesn't really jump off the page when you are
reading over the code in a code review.
Instead of using the shortcut, take the time necessary to turn this into the full notation. Doing so will protect you in the future. The final notation would look like this:
if (i > 3) {
doSomething();
}
Now when anyone goes in to add additional logic, it becomes readily apparent where to put the code and what will happen when you do.
Declare All Variables First
Most languages that conform to the C-family style will not put an item into memory until the program execution hits the line where the item is initialized.
JavaScript is not like most other languages. It utilizes function-level scoping of variables and functions. When a variable is declared, the declaration statement gets hoisted to the top of the function. The same is true for functions. For example, this is permissible (if horrible) format:
function simpleExample(){
i = 7;
console.log(i);
var i;
}
What happens behind the scenes is that the var i;
line declaration gets hoisted to the top of the simpleExample
function. To make matters more complicated, not only the declaration of
a variable gets hoisted but the entire function declaration gets
hoisted. Let's look at an example to make this clearer:
function complexExample() {
i = 7;
console.log(i); //The message says 7
console.log(testOne()); //This gives a type error saying testOne is not a function
console.log(testTwo()); //The message says "Hi from test two"
var testOne = function(){ return 'Hi from test one'; }
function testTwo(){ return 'Hi from test two'; }
var i = 2;
}
Let's rewrite this function the way JavaScript sees it once it has hoisted the variable declarations and functions:
function complexExample() {
var testOne;
function testTwo(){ return 'Hi from test two'; }
var i;
i = 7;
console.log(i); //The message says 7
console.log(testOne()); //This gives a type error saying testOne is not a function
console.log(testTwo()); //The message says "Hi from test two"
testOne = function(){ return 'Hi from test one'; }
i = 2;
}
See the difference? The function testOne
didn't get
hoisted because it was a variable declaration (the variable is named
testOne and the declaration is the anonymous function). The variable i
gets its declaration hoisted and the initialization actually becomes an assignment down below.
In order to minimize mistakes and reduce the chances of introducing hard to find bugs in your code, always declare your variables at the top of your function and declare your functions next, before you need to use them. This reduces the chances of a misunderstanding about what is going on in your code.
Do Not Use "With"
It is possible to shorten a long namespace using the with statement. For instance, this is technically correct syntax:
with (myNamespace.parent.child.person) {
firstName = 'Jon';
lastName = 'Smyth';
}
That is equivalent of typing the following:
myNamespace.parent.child.person.firstName = 'Jon';
myNamespace.parent.child.person.lastName = 'Smyth';
The problem is that there are times when this goes badly wrong. Like many of the other common pitfalls of JavaScript, this will work fine in most circumstances. The better method of handling this issue is to assign the object to a variable and then reference the variable like so:
var p = myNamespace.parent.child.person;
p.firstName = 'Jon';
p.lastName = 'Smyth';
This method works every time, which is what we want out of a coding practice.
Be Careful Using typeof
Again, the edge cases here will bite you if you aren't careful. Normally, typeof
returns the string representation of the value type ('number',
'string', etc.) The problem comes in when evaluating NaN ('number'),
null ('object'), and other odd cases. For example, here are a couple of
comparisons that might be unexpected:
var i = 10;
i = i - 'taxi'; //Here i becomes NaN
if (typeof(i) === 'number') {
console.log('i is a number');
} else {
console.log('You subtracted a bad value from i');
}
The resulting alert message would be "i is a number", even though clearly it is NaN (or "Not a Number"). If you were attempting to ensure the passed in value (here it is represented by 'taxi') subtracted from i was a valid number, you would get unexpected results.
While there are times when it is necessary to try to determine the
type of a particular value, be sure to understand these (and other)
peculiarities about typeof
that could lead to undesirable results.
Treat parseInt With Care
Just like the typeof
function, the parseInt
function has quirks that need to be understood before it is used. There
are two major areas that lead to unexpected results. First, if the
first character is a number, parseInt
will return all of the number characters it finds until it hits a non-numeric character. Here is an example:
parseInt("56"); //Returns 56
parseInt("Joe"); //Returns NaN
parseInt("Joe56"); //Returns NaN
parseInt("56Joe"); //Returns 56
parseInt("21.95"); //Returns 21
Note that last example I threw in there to trip you up. The decimal
point is not a valid character in an integer, so just like any other
character, parseInt
stops evaluating on it. Thus, we get 21 when evaluating 21.95 and no rounding is attempted.
The second pitfall is in the interpretation of the number. It used to be that a string with a leading zero was determined to be a number in octal format. Ecmascript 5 (JavaScript is an implementation of Ecmascript) removed this functionality. Now most numbers will default to base 10 (the most common numbering format). The one exception is a string that starts with "0x". This type of string will be assumed to be a hexadecimal number (base 16) and it will be converted to a base 10 number on output. To specify a number's format, thus ensuring it is properly evaluated, you can include the optional parameter called a radix. Here are some more examples to illustrate these possibilities:
parseInt("08"); //Returns 8 - used to return 0 (base 8)
parseInt("0x12"); //Returns 18 - assumes hexadecimal
parseInt("12", 16); //Returns 18, since base 16 is specified
Do Not Use Switch Fall Through
When you execute a switch
statement, each case
statement should be concluded by a break
statement like so:
switch(i) {
case 1:
console.log('One');
break;
case 2:
console.log('Two');
break;
case 3:
console.log('Three');
break;
default:
console.log('Unknown');
break;
}
If you were to assign the value of 2 to the variable i
,
this switch statement would fire an alert that says "Two". The language
does permit you to allow fall through by omitting the break statement(s)
like so:
switch(i) {
case 1:
console.log('One');
break;
case 2:
console.log('Two');
case 3:
console.log('Three');
break;
default:
console.log('Unknown');
break;
}
Now if you passed in a value of 2, you would get two alerts, the first one saying "Two" and the second one saying "Three". This can seem to be a desirable solution in certain circumstances. The problem is that this can create false expectations. If you do not see that a break statement is missing, you may add logic that gets fired accidentally. Conversely, you may notice later that a break statement is missing and you might assume this is a bug. The bottom line is that fall through should not be used intentionally in order to keep your logic clean and clear.
Avoid For...In Loops
The For...In loop works as it is intended to work, but how it works surprises people. The basic overview is that it loops through the attached, enumeration-visible members on an object. It does not simply walk down the index list like a basic for loop does. The following two examples are NOT equivalent:
// The standard for loop
for(var i = 0; i < arr.length; i++) {}
// The for...in loop
for(var i in arr) {}
In some cases, the output will act the same in the above two cases. That does not mean they work the same way. There are three major ways that for...in is different than a standard for loop. These are:
- It loops through all of the enumeration-visible members, which means it will pick up functions or other items attached to the object or its prototype.
- The order is not predictable (especially cross-browser).
- It is slower than a standard for loop.
If you fully understand for...in and know that it is the right choice for your specific situation, it can be a good solution. However, for the other 99% of situations, you should use a standard for loop instead. It will be quicker, easier to understand, and less likely to cause weird bugs that are hard to diagnose.
Use Var to Declare Variables
When declaring a variable, always use the var keyword unless you are specifically attaching the variable to an object. Failure to do so attaches your new variable to the global scope (window if you are in a browser). Here is an example to illustrate how this works:
function carDemo() {
var carMake = 'Dodge';
carModel = 'Charger';
}
console.log(carMake); //Undefined, since carMake is defined inside the testing function scope
console.log(carModel); //Charger, since this variable has been implicitly attached to window
The declaration of the carModel variable is the equivalent of saying window.carModel = 'Charger';
.
This clogs up the global scope and endangers your other JavaScript code
blocks, since you might inadvertently change the value of a variable
somewhere else.
Avoid Reserved / Special Words
JavaScript is rather flexible with what it allows you to do. This
isn't always a good thing. For instance, when you create a function, you
can specify that one of the parameters be named arguments
.
This will overwrite the arguments object that every function is given
by inheritance. This is an example of a special word that isn't truly
reserved. Here is an example of how it would work:
// This function correctly accesses the inherited
// arguments parameter
function CorrectWay() {
for(var i = 0; i < arguments.length; i++) {
console.log(arguments[i]);
}
}
// You should never name a parameter after
// a reserved or special word like "arguments"
function WrongWay(arguments) {
for(var i = 0; i < arguments.length; i++) {
console.log(arguments[i]);
}
}
// Outputs 'hello' and 'hi'
CorrectWay('hello', 'hi');
// Outputs 'h', 'e', 'l', 'l', and 'o'
WrongWay('hello', 'hi');
There are also reserved words that will cause you issues when you attempt to run your application. A complete listing of these words can be found at the Mozilla Developer Network. While there are work-arounds to use some of these words, avoid doing so if at all possible. Instead, use key words that won't conflict with current or potential future reserved or special words.
Read Good Code
As with any software development language, reading the code of other developers will help you improve your own skills. Find a popular open source library and peruse the code. Figure out what they are doing and then identify why they chose to do things that way. If you can't figure it out, ask someone. Push yourself to learn new ways to attach common problems.
Conclusion
JavaScript is not C#. It is not Java or Java-lite. It is its own language. If you treat it as such, you will have a much easier time navigating its particular peculiarities. As you may have noticed, the common theme throughout many of these best practices is that there are hidden pitfalls that can be avoided by simply modifying how you approach certain problems. Little formatting and layout techniques can make a big difference in the success of your project.
Before I finish, I wanted to point out that there are a number of
best practices related to JavaScript in HTML that I have not mentioned.
For instance, a simple one is to include your JavaScript files at the
bottom of your body
tag. This omission is intentional.
While I've made passing references to both the browser and Visual
Studio, the above tips are purely about JavaScript. I will be writing a
separate article that covers JavaScript in the browser.
Thus concludes my attempt at compiling a list of JavaScript best practices. Please be sure to let me know if you have others that you think should be added to the list.
- Lượt gửi (0)
- Mới
Tạo video doanh nghiệp của bạn bằng AI chỉ với giọng nói hoặc văn bản
chatGPTaz.com
Nói chuyện với ChatGPT bằng ngôn ngữ mẹ đẻ của bạn
Ứng dụng AI Video
Ứng dụng video AI MIỄN PHÍ đầu tiên của bạn
Deepfake Video
Deepfake AI Video Maker
Deepfake
Deepfake AI Video Maker
AI Deep Fake
Deepfake AI Video Maker
AIvidio
AI Video Mobile Solutions
AIvideos
AI Video Platform & Solutions
AIvedio
AI Video App Maker
Faceswap AI trực tuyến
Đổi mặt Video, Ảnh & GIF ngay lập tức với Công cụ AI mạnh mẽ - Faceswap AI Trực tuyến MIỄN PHÍ
Faceswap AI trực tuyến
Đổi mặt Video, Ảnh & GIF ngay lập tức với Công cụ AI mạnh mẽ - Faceswap AI Trực tuyến MIỄN PHÍ
Temu tặng $500 cho người dùng mới
Claim Free Temu $500 Credit via Affiliate & Influencer Program
Tín dụng quảng cáo TikTok miễn phí
Làm chủ quảng cáo TikTok cho hoạt động tiếp thị doanh nghiệp của bạn
Dall-E-OpenAI.com
Tự động tạo ra hình ảnh sáng tạo với AI
chatGPT4.win
Nói chuyện với ChatGPT bằng ngôn ngữ mẹ đẻ của bạn
Sản phẩm AI đầu tiên của Elon Musk - Grok/UN.com
Nói chuyện với Grok AI Chatbot bằng ngôn ngữ của bạn
Công cụ.win
Mở trung tâm công cụ miễn phí để mọi người sử dụng với hàng trăm công cụ
GateIO.gomymobi.com
Airdrop miễn phí để nhận, chia sẻ lên đến 150.000 đô la cho mỗi dự án
iPhoneKer.com
Tiết kiệm tới 630$ khi mua iPhone 16 mới
Mua Robot Tesla Optimus
Đặt mua Tesla Bot: Robot Optimus Gen 2 ngay hôm nay với giá dưới 20.000 đô la