Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to write high quality JavaScript code

2025-03-31 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

In this issue, the editor will bring you about how to write high-quality JavaScript code. The article is rich in content and analyzed and described from a professional point of view. I hope you can get something after reading this article.

Write maintainable code

BUG repair of software takes a lot of effort. Especially after the code has been released, the cost of maintenance becomes higher and higher over time. As soon as you find BUG, fix it immediately, your code is still hot, and you don't need to recall it, because it's just written. But when you do other tasks and almost completely forget the code, you need to:

◆ re-learn and understand the problem

◆ understands how the code solves the problem

Another problem is that in large projects or companies, the people who solve BUG are often not the ones who produce BUG, and they are not the ones who found BUG. So reducing the time it takes to understand the code is the most important issue, whether it's written by yourself or by other members of the team, because we all want to do something new and interesting, not to maintain the old code.

Another common problem in development is that you often spend more time reading code than writing code. Sometimes when you delve into a problem, you can spend the whole afternoon thinking about coding. The code worked at the time, but as the development went on, other things changed a lot, and you had to review and write the code yourself. For example:

◆ and BUG have not been solved.

◆ has added new features.

◆ programs need to be run in a new environment (such as a newly launched browser)

There is something wrong with the ◆ code

The ◆ code needs to be rewritten because the schema has been modified and even another language will be used

For these reasons, it may take you a few weeks to read the code you wrote one afternoon. So writing maintainable code is critical to the success of the software.

Maintainable code includes:

◆ readability

◆ continuity

◆ predictability

◆ seems to have been written by one person.

◆ has documentation.

Minimize global variables

Javascript uses functions to specify scopes. A variable declared inside a function is not visible on the outside. So, a global variable is a variable that is declared outside any function or that is not declared.

In Javascript, there is an accessible global object outside of any function, and every global variable you create is a property of that object. In browsers, window is usually used to refer to this global variable for convenience. The following code shows how to create a global variable:

Myglobal = "hello"; / / antipattern console.log (myglobal); / / "hello" console.log (window.myglobal); / / "hello" console.log (window ["myglobal"]); / / "hello" console.log (this.myglobal); / / "hello"

The problem of global variables

The problem with global variables is that they are shared in all your code or in one page. They are under the same namespace, which usually causes variable names to conflict-two variables with the same name, but for different uses.

Usually you need to introduce other people's code into some pages, such as:

◆ third-party JS library

Script of ◆ Advertising partner

◆ third-party user behavior analysis or statistical script

Different components, buttons, etc., of ◆

Adding one of the third-party components defines a global variable: result. Then in your program, a global variable result is also defined. The result of * * will overwrite the result before the point, so that the third-party script will stop working.

So, in order to be script-friendly, the fewer global variables you use on a page, the better. There are some ways to reduce global variables later, such as using namespaces or self-executing anonymous functions, but the way to avoid global variables is to use the var keyword to declare variables.

Because of the two features of javascript, it is very easy to create a global variable. *, you can use a variable that is not even declared. Second, in javascript, all undeclared variables become a property of the global object (just like a declared global variable). Look at this example:

Function sum (xPowery) {result = x + y; return result;}

In this code, result is used without being declared, and the code works well, but after calling this function, there will be an additional global variable named result, which is the root of all the problems.

The solution to this problem is to use var:

Function sum (xPowery) {var result = x + y; return result;}

A bad habit is to use chained assignments when declaring variables, in which case an is a local variable, but b becomes a global variable.

Function foo () {var aquibund 0;. }

This is because the expression b = 0 is executed first, and b is not declared when it is executed, so b becomes a global variable, and then returns the value of the expression 0 to the declared variable a, in other words, as if you entered:

Var a = (baked 0)

If you have already declared variables, there is no problem with this chained assignment:

Function foo () {var a _ r b;...}

Another reason to avoid using global variables is to consider the portability of the program. If you want your code to work in different environments, using global variables is likely to conflict with global variables in the new system (or no problem in the previous system).

Forget the influence of var

Another difference between global variables declared with var and global variables that are not generated with var is deletion:

Global variables created with var declarations cannot be deleted

Global variables that are not declared with var can be deleted

This means that the global variables generated without the var declaration are not real variables, they are just properties of the global object. Properties can be deleted through delete, but variables cannot:

/ / define three globals var global_var = 1; global_novar = 2; / / antipattern (function () {global_fromfunc = 3; / / antipattern} ()); / / attempt to delete delete global_var; / / false delete global_novar; / / true delete global_fromfunc; / / true / / test the deletion typeof global_var; / / "number" typeof global_novar; / / "undefined" typeof global_fromfunc; / / "undefined"

In ES5's strict mode, assigning a value to a declared variable will report an error.

Read global object

In the browser, you can read the global object through the window variable (unless you redefine the window object inside the function). However, in some environments, it may not be called window, so you can use the following code to get the global object:

Var global = (function () {return this;}) ()

The reason you can get the global object in this way is that inside the function, this points to the global object. But this won't work in ES5's strict mode, and you need to adapt to some other modes. When you develop your own library, you can encapsulate your code in an immediate function and pass this as an argument.

Single var mode

Just using a var keyword at the top of your code has the following benefits:

◆ can see all the required variables in one place.

◆ avoids using an undefined variable

◆ helps you remember declared variables and reduce global variables

◆ 's more streamlined code

Writing is simple:

Function func () {var a = 1, b = 2, sum = a + b, myobject = {}, I, j; / / function body... }

Multiple variables are declared with a var and a comma. It is also a good idea to assign default values to variables when declaring, which can avoid some logic errors and improve the readability of the code. Then when you read the code, you can easily guess the use of the variable according to the default value of the variable.

You can also do some practical work when declaring variables, such as sum = a + b; in addition, when you manipulate the DOM element, you can save the reference to the DOM element in a variable:

Function updateElement () {var el = document.getElementById ("result"), style = el.style; / / do something with el and style... }

Abused var

JavaScript allows you to have multiple var statements inside a function, but they all behave as if they were declared at the top of the function. This feature can cause some strange logic problems when you use a variable and then declare it later. For JavaScript, as long as the variable is in the same scope, it is considered declared, even before the var statement. Look at this example:

Myname = "global"; / / global variable function func () {alert (myname); / / "undefined" var myname = "local"; alert (myname); / / "local"} func ()

In this example, you might expect global to pop up a second time and local to pop up a second time. Because the myname has not been declared with var for the second time, this should be the myname of the global variable, and then the alert should be followed by the value of local. In fact, this is not the case, as long as you have var myname in the function, then js thinks that you declare the variable in this function, but when reading the value of this variable, because the var statement has not yet been executed, it is undefined, very strange logic. The above code is equivalent to:

Myname = "global"; / / global variable function func () {var myname; / / same as-> var myname = undefined; alert (myname); / / "undefined" myname = "local"; alert (myname); / / "local"} func ()

Let's explain this phenomenon. In the parsing of the code, there are two steps. The * * step first deals with the declaration of the variable function, which deals with the context of the entire code. The second step is the runtime of the code, creating function expressions and undefined variables. In fact, we just assumed the concept, which is not in the ECMAScript specification, but this behavior is often explained in this way.

For cycle

In the for loop you will iterate over some array elements or some HTML elements. For loops often look like this:

For (var I = 0; I

< myarray.length; i++) { // do something with myarray[i] } 这样写的问题在于,每一次迭代的时候都会计算数组的长度,尤其在这个参数不是一个数组而是一组HTML元素的时候会降低你的程序的性能。 HTML元素的集合在页面上,这样每次都会去再页面上查找相应的元素,这是非常耗时的。所以对于for循环,你需要预先保存数组的长度,这样写: for (var i = 0, max = myarray.length; i < max; i++) { // do something with myarray[i] } 这样缓存了参数的长度,在每次迭代的时候就不用再去查找计算了。 在查找HTML元素集合的时候,缓存参数长度可以带来可观的性能提升,Safari下面提高两倍的速度,在IE7下面提高190倍的速度。 需要注意的是,当你需要操作修改DOM元素的数量的时候,你肯定希望这个值是随时更新的而不是一个常量。 使用下面的单一var模式,你也可以把var提到循环之外: function looper() { var i = 0, max, myarray = []; // ... for (i = 0, max = myarray.length; i < max; i++) { // do something with myarray[i] } } 这个模式可以增强整个代码的连续性,但是不好的一点是当你重构代码的时候复制粘贴就没那么容易了。例如:如果你想在其他函数中也使用这个循环,那你需要确定在新的函数中处理好了i和max(或许还需要删掉这个)。 这个函数还有两个点可以优化的: ◆可以少一个变量(不需要max) ◆递减到0,一个数字与0比较比这个数字与另外一个数字比较更快 所以就可以写为: var i, myarray = []; for (i = myarray.length; i--;) { // do something with myarray[i] } 针对第二点: var myarray = [], i = myarray.length; while (i--) { // do something with myarray[i] } 这是两个比较微小的点的优化。另外,JSLint可能对于i-会有意见。 for-in循环 for-in循环用来迭代非数组的对象。使用for-in循环通常也成为枚举。 从技术上来说,你也可以用for-in来循环数组,因为数组也是对象,但是不推荐。如果数组有一些自定义的扩展函数,那么就会出错。另外,对象属性的顺序在for-in循环中也是不确定的。所以***还是用普通的循环来循环数组用for-in来循环对象。 在循环对象的过程中,使用hasOwnProperty()方法来检验是对象本身的属性还是原型链上的属性很重要。 看看下面的这个例子。 // the object var man = { hands: 2, legs: 2, heads: 1 }; // somewhere else in the code // a method was added to all objects if (typeof Object.prototype.clone === "undefined") { Object.prototype.clone = function () {}; } 在这个例子中,我们有一个简单的称作man的对象字面量。在其他man定义之前或之后的地方,对象原型有一个很有用的clone()方法。因为原型链的原因,所有的对象都自动获得了这个方法。为了在枚举man对象的时候出现clone方法,你需要使用hasOwnProperty方法来区别。如果没有区别来自原型链的方法,那么就会有一些意想不到的事情发生: // 1. // for-in loop for (var i in man) { if (man.hasOwnProperty(i)) { // filter console.log(i, ":", man[i]); } } /* result in the console hands : 2 legs : 2 heads : 1 */ // 2. // antipattern: // for-in loop without checking hasOwnProperty() for (var i in man) { console.log(i, ":", man[i]); } /* result in the console hands : 2 legs : 2 heads : 1 clone: function() */ 另外一种使用方法如下: for (var i in man) { if (Object.prototype.hasOwnProperty.call(man, i)) { // filter console.log(i, ":", man[i]); } } 这样写的好处是可以防止man重新定义了hasOwnProperty方法导致的冲突。如果不想写这么长的一串,你也可以这样: var i, hasOwn = Object.prototype.hasOwnProperty; for (i in man) { if (hasOwn.call(man, i)) { // filter console.log(i, ":", man[i]); } } 严格意义上讲,不适用hasOwnProperty也不是什么错误。根据任务的难度和你对代码的自信程度,你也可以不用这个直接循环。但是当你不确定的时候,***还是使用这个方法检测一下。 另外一种格式上的改变(不会通过jsLint的检查),去掉for的大括号,然后把if放在同一行。这样做的好处可以让循环体更加突出,缩进也就少一些: // Warning: doesn't pass JSLint var i, hasOwn = Object.prototype.hasOwnProperty; for (i in man) if (hasOwn.call(man, i)) { // filter console.log(i, ":", man[i]); } 不要扩展内建的原型 扩展原型的构造函数,可以提供一些很强大的功能,但是有时候他太强大了。 有时候你会去扩展Object(),Array(),Fucntion()的原型方法,这样会导致可维护性的问题,因为这会让你的代码的移植性变差。其他的开发人员使用你的代码的时候,可能只需要原生的方法,并不需要额外的功能。 另外,你添加进去的方法,如果在循环的时候没有使用hasOwnProperty方法就会被遍历出来,这会让人很迷惑。 所以,***还是不要扩展基本的对象。除非是下面的情况: ◆你确定在将来根据ECMAScript规范,浏览器会添加相应的原型方法,那么是可以的,你只不过是提前实现了这个功能。 ◆你确定的你要实现的方法不存在-或许有时候在代码的其他的地方实现了,或者有的浏览器支持,这都是不行的。 ◆有非常清晰的文档,并且与团队成员沟通过 如果在这些情况之下,那么你就可以添加,***是下面这种形式: if (typeof Object.prototype.myMethod !== "function") { Object.prototype.myMethod = function () { // implementation... }; } switch模式 按照下面的风格写switch的话,可以提高你的代码可读性和健壮性: var inspect_me = 0, result = ''; switch (inspect_me) { case 0: result = "zero"; break; case 1: result = "one"; break; default: result = "unknown"; } 需要注意下面几个方面: ◆将case和switch对齐。 ◆case的内容缩进 ◆每一个case之后都有一个清晰的break ◆避免顺序往下执行case,非要如此的话,文档一定要写清楚 ◆***使用default,保证在没有命中case的情况下也有反馈 避免隐藏的类型转换 Javascript在你比较两个变量的时候会进行类型的转换,这就是为什么 false == 0或者"" == 0会返回true。 为了避免这种隐藏的类型转换带来的迷惑,***使用===或者!==操作符来比较: var zero = 0; if (zero === false) { // not executing because zero is 0, not false } // antipattern if (zero == false) { // this block is executed... } 还有另外一种流派持这样的观点:当==够用时使用===就是多余的。比如,当你使用typeof的时候你知道会返回string,所以没必要使用严格的检验。然而,JSLint要求严格检验;他最大程度使代码在阅读的时候减少歧义,("这个==是故意呢还是疏漏?")。 避免使用eval() 如果你在你的代码中使用eval(),那么要记住"eval() is evil"。这个方法会将传入的字符串当做js代码来执行。如果代码是在运行前就确定的,那么没有必要使用eval()。如果代码是在运行时动态确定的,那么也有其他更安全的办法。例如使用方括号形式访问元素的属性: // antipattern var property = "name"; alert(eval("obj." + property)); // preferred var property = "name"; alert(obj[property]); 使用eval()还有安全问题,比如你运行网络上的一段代码,而这段代码又被别人篡改了。在处理Ajax请求返回的JSON数据的时候,***还是使用浏览器内建的处理方法,如果对于低端的浏览器不支持的,可以从JSON.org上下载对应的处理库。 另外还要记住使用setTimeout、setInterval以及Function的构造函数的是,传入的字符串的参数,js的处理方法跟eval()类似,所以也要注意。因为,js会把你传入的字符串解析执行: // antipatterns setTimeout("myFunc()", 1000); setTimeout("myFunc(1, 2, 3)", 1000); // preferred setTimeout(myFunc, 1000); setTimeout(function () { myFunc(1, 2, 3); }, 1000); 使用Function的构造函数,跟eval()差不多,也要注意。这是个非常有用的功能,但是常常被错用。如果你必须使用eval(),那么可以考虑new一个Function来替代。另外的一个好处就是,使用Function的构造函数,函数的作用域在本方法内,这样你使用var声明的变量就不会变成全局的。另外一个防止eval()生成全局变量的办法就是使用匿名函数。 看看下面这个例子,只有un变量最终是全局的: 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 eval()和Function构造函数的另一个区别就是eval()会影响到作用域,而Function则相当于一个沙盒。例如: (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 }()); 使用parseInt()转换处理数字 使用parseInt()你可以将字符串转为数字。这个方法支持第二个表示进制的参数,常常被忽略。问题常常在处理一段以0开始的字符串的时候。在ECMAS3标准中,以0开始表示八进制,但是在ES5中又改了,所以为了避免麻烦,***还是标明第二个参数。 var month = "06", year = "09"; month = parseInt(month, 10); year = parseInt(year, 10); 在这个例子中,如果你使用parseInt(year),就会返回0,因为09被认为是8进制数字,然而9是非法的八进制字符,所以返回0。 其他的可以把字符串转为数字的方法有: +"08" // result is 8 umber("08") // 8 这些通常都比parseInt()快一些,因为parseInt并不只是简单的转换。但是如果你的输入是"08 hello"这样的,那么parseInt()也会返回8,但是其他的方法就只能返回NaN。 编码规范 编码的时候遵循一定的规范,可以让你的代码增强可移植性,并且更加便于阅读和理解。加入团队的新人,在阅读了代码规范之后,可以更加快速的溶入团队,并理解其他人员开发的代码。 在一些讨论会议上,规范往往都是争论的焦点(比如缩进的形式)。所以如果你打算为你团队的编码规范提一些建议,那就准备好一场激烈的辩论和反对意见。要记住,建立和实施规范是非常重要的。 缩进 代码如果没有缩进,那基本上没法阅读了。比这更糟的是不规范的缩进,看着好像缩进了,但是乱七八糟摸不着头脑。所以缩进的使用必须规范。 有些开发人员喜欢使用tab键来缩进,因为在每一个编辑器里面都可以自己设置想要的tab值。有的人喜欢四个空格。如果团队遵循统一的规范,这也不是什么问题。比如本文就是四个空格,这也是JSLint推荐的。 那么什么该缩进呢?很简单,大括号。这样就是说包括函数体,循环,ifs,switch,以及对象字面量的属性。看看这个例子: 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;}

Curly braces

Curly braces should be used, especially where available or not, if your if statement or for loop has only one sentence, then curly braces are not necessary, but use curly braces in this case. This keeps the code consistent and makes it easy to upgrade.

Suppose your for loop has only one sentence. You don't have to use curly braces and you won't make any mistakes.

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

But what if you want to add something else to this loop later?

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

At this point, although the second alert is indented, it is still outside the loop. Therefore, curly braces should be used at all times. The if statement is the same:

/ / bad if (true) alert (1); else alert (2); / / better if (true) {alert (1);} else {alert (2);}

Curly braces position

Developers also often argue about the location of curly braces, on the same line or the next line?

In specific examples, this is a matter of opinion. But there are exceptions. What if the program does different parsing according to different locations? This is because of the semicolon insertion mechanism, which js is not picky about, and he will help you add it after you do not add a semicolon. This is a problem when the function returns an object literal and the curly braces are written on the next line:

/ / warning: unexpected return value function func () {return / / the following cannot be read {name: "Batman"}}

If you want this function to return the literal amount of an object with the name attribute, this function cannot, because the semicolon inserted should return an undefied value.

So, the conclusion of * is that curly braces must be used and written on the same line.

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

About the semicolon: like curly braces, it must be written. This is not only to implement strict rules for writing procedures, but also to solve some ambiguities when necessary, such as the previous example.

Space

The correct use of spaces can also increase the readability and consistency of the program. When you write a sentence, you will have some pauses after commas and periods. Such logic can be imitated in js.

Spaces should be used:

After the semicolon in the ◆ loop

The variables in the ◆ loop initialize for (var I = 0, max = 10; I < max; I + = 1) {... }

Var a = [1,2,3] after the comma separator in the ◆ array

Comma var o = {a: 1, b: 2} in literals of ◆ object

MyFunc (a, b, c) between parameters of ◆ function

◆ function myFunc () {} before the curly braces when the function is declared

◆ anonymous function var myFunc = function () {}

Other good places to use spaces are on both sides of those operators, such as +, -, *, =, =,! = =, & &, | |, + =, and so on.

/ / generous and consistent spacing / / makes the code easier to read / / allowing it to "breathe" var d = 0, a = b + 1; if (a & b & c) {d = a% c; a + = d;} / / antipattern / / missing or inconsistent spaces / / make the code confusing var d = 0, a = b + 1; if (a & b & c) {d = a% c A + = d;}

* * one thing to note about spaces, the space before the curly braces. * use spaces:

◆ uses spaces before curly braces for function definitions, id-else,case, loops, and literal quantities of objects

◆ uses spaces between curly braces} and else and while

One argument against adding spaces is to increase the file size, but this problem does not exist after compression. One aspect of improving the readability of code that is often overlooked is vertical spaces, where you can use blank lines to separate code, just like paragraphs when writing articles.

Naming convention

One aspect that can improve code portability and maintainability is the naming convention. In other words, it is always a consistent practice when choosing a variable name.

No matter what naming convention is used, it is not very important, it is important to determine the specification and then follow it.

Constructor initials are capitalized

There are no classes in javascript, but you can use new to achieve the same goal.

Because a constructor is also a function, it is very useful for developers to tell whether it is a constructor or an ordinary function by name. So capitalize the first letter of the constructor and write the first letter of the ordinary function as a hint. You can tell the difference at a glance.

The separation of words

When your variable name or function name is made up of several words, it is also a very good experience if you can successfully distinguish which words the variable name is composed of. This naming convention is called hump style. The so-called hump style begins with lowercase letters, followed by a capital letter of each word.

For the constructor * capitalized, MyConstructor (), for ordinary functions, use hump myFunction (), calculateArea ().

What about variables? some people use humps, but a better way is to use underscores to distinguish them. First_name,favorite_bands, and old_company_name. It also allows you to distinguish between functions and variables at a glance.

Other naming conventions

Sometimes, developers also use naming conventions to replace and compensate for some language features.

For example, in javascript, there is no way to define constants (although there is a Number.MAX_VALUE), so developers use all uppercase names to represent immutable constants. Var PI = 3.14, MAX_WIDTH = 800, respectively.

Another specification is to use the initials of global variable names. Doing so strengthens developers to minimize global variables and make them easy to identify.

Another specification is to simulate private members in functions. Although private variables can be implemented in javascript, developers prefix them with an underscore in order to make it easier to distinguish. For example:

Var person = {getName: function () {return this._getFirst () +'+ this._getLast ();}, _ getFirst: function () {/ /...}, _ getLast: function () {/ /...}}

In this example, getName is a public function that is part of API, and _ getFirst,_getLast is meant to be private. Although it is still a public function, hi adds this prefix to indicate that it is not guaranteed to run in future versions, so it should not be used directly. Note that this is not recommended in JSLint unless you set the nomen option to false.

There are several other specifications that represent private members:

◆ uses underscores at the end, such as name_ and getElements_

◆ uses an underscore to represent the protected member _ protected, and two underscores to represent the private member _ _ private

◆ in firefox, there are some variables that are not native to the language, starting with two underscores, ending with _ _ proto__ and _ _ parent__

Write notes

You have to comment on your code, even if it doesn't seem to be taken over. Sometimes, when you finish studying a problem, and then you look at the code and think it's obvious, but looking back a week or two later, you'll be confused.

Of course, you can't comment too much: every variable, every line of code is commented. But it is usually necessary to document the function, parameters, return values, and other complex logic and algorithms. Come to think of it, readers of your code can read comments to get a general idea of what your code is doing and what it needs, which is much faster than reading the code directly. When you have five or six lines of code to do a specific task, then the reader can understand your purpose through one line of code, and then skip the code. With regard to comments, there is no hard proportion to how many comments are required for how much code. Sometimes, some code, such as regular expressions, must have more comments than the code itself.

Writing comments is a specification that must be followed, and to keep comments up-to-date, an outdated comment is less confusing than not writing a comment at all.

The above is the editor for you to share how to write high-quality JavaScript code, if you happen to have similar doubts, you might as well refer to the above analysis to understand. If you want to know more about it, you are welcome to follow the industry information channel.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report