>  기사  >  웹 프론트엔드  >  사용자 정의 및 유지 관리가 가능한 JS 코드를 작성하는 방법

사용자 정의 및 유지 관리가 가능한 JS 코드를 작성하는 방법

php中世界最好的语言
php中世界最好的语言원래의
2018-06-04 10:10:161394검색

이번에는 사용자 정의 가능하고 유지 관리 가능한 JS 코드를 작성하는 방법과 사용자 정의 가능하고 유지 관리 가능한 JS 코드 작성 시 주의 사항이 무엇인지 보여드리겠습니다. 다음은 실제 사례입니다.

1.1 서식

들여쓰기 수준에 대하여: 저는 "탭 또는 공백" 대 "2, 4, 6, 8 공백" 논쟁을 시작하고 싶지 않습니다. 이 주제는 들여쓰기와도 관련이 있습니다. 프로그래머의 가치에. 다음 세 가지 사항만 기억하면 됩니다.

코드는 들여쓰기되고 정렬되어야 합니다.

같은 프로젝트에서 Tab과 Space를 혼합하지 마세요.

팀 스타일을 일관되게 유지하세요.

후행 세미콜론 정보: 파서의 자동 세미콜론 삽입(ASI) 메커니즘에 의존하여 JS 코드는 세미콜론이 생략되어도 정상적으로 작동할 수 있습니다. ASI는 코드에서 세미콜론을 사용해야 하지만 존재하지 않는 위치를 자동으로 찾아서 삽입합니다. 대부분의 경우 ASI는 오류 없이 세미콜론을 올바르게 삽입합니다. 그러나 ASI의 세미콜론 삽입 규칙은 매우 복잡하고 기억하기 어렵기 때문에 세미콜론을 생략하지 않는 것이 좋습니다. 대부분의 스타일 가이드(JavaScript 표준 스타일 제외)에서는 세미콜론을 생략하지 않는 것이 좋습니다.

줄 길이 정보: 대부분의 언어 및 JS 코딩 스타일 가이드에서는 줄 길이를 80자로 지정합니다. 이 값은 오래전 텍스트 편집기에서 한 줄의 최대 문자 제한, 즉 편집기에서는 한 줄의 최대 문자 수를 80자까지만 표시할 수 있습니다. 80자를 초과하는 줄은 줄 바꿈되거나 숨겨지므로 원하지 않습니다. 나는 또한 줄 길이를 80자로 제한하는 경향이 있습니다.

줄 바꿈 정보: 줄 길이가 한 줄의 최대 문자 제한에 도달하면 한 줄을 두 줄로 수동으로 분할해야 합니다. 일반적으로 우리는 연산자 뒤에 줄을 래핑하고 다음 줄에는 두 가지 수준의 들여쓰기가 추가됩니다(개인적으로는 한 개의 들여쓰기는 괜찮지만 들여쓰기가 전혀 없는 것은 아니라고 생각합니다). 예:

callFunc(document, element, window, 'test', 100, true);

이 예에서 쉼표는 연산자이므로 이전 줄의 끝으로 사용해야 합니다. ASI 메커니즘은 일부 시나리오에서 줄 끝에 세미콜론을 삽입하기 때문에 이 줄바꿈 위치는 매우 중요합니다. 항상 줄 끝에 연산자를 배치함으로써 ASI는 자체적으로 세미콜론을 삽입하지 않으므로 오류가 방지됩니다. 이 규칙에는 한 가지 예외가 있습니다. 변수에 값을 할당할 때 두 번째 줄의 위치는 할당 연산자의 위치와 정렬되어야 합니다. 예:

var result = something + anotherThing + yetAnotherThing + somethingElse +
             anotherSomethingElse;

이 코드에서 anotherSomethingElse 변수와 줄 시작 부분의 항목은 코드의 가독성을 보장하고 래핑된 텍스트의 컨텍스트를 한 눈에 명확하게 볼 수 있도록 왼쪽 정렬됩니다.

빈 줄 정보: 프로그래밍 사양에서 빈 줄은 종종 무시되는 측면입니다. 일반적으로 코드는 하나의 큰 연속 텍스트 블록이 아니라 읽을 수 있는 일련의 단락처럼 보여야 합니다. 때로는 코드 조각의 의미가 다른 코드 조각과 관련이 없는 경우 의미상 관련된 코드가 함께 표시되도록 빈 줄을 사용하여 구분해야 합니다. 일반적으로 다음 시나리오에서는 빈 줄을 추가하는 것이 좋습니다.

메소드 사이.

지역 변수와 메서드의 첫 번째 문 사이.

여러 줄 또는 한 줄 주석 앞에.

가독성을 높이기 위해 메소드 내의 논리 조각 사이에 빈 줄을 삽입하세요.

1.2 이름 지정

이름 지정은 변수, 상수, 함수, 생성자의 네 가지 범주로 나뉩니다. 변수와 함수는 작은 카멜 케이스 명명법(첫 글자는 소문자)을 사용하고 생성자는 큰 카멜 케이스 명명법(첫 글자는 대문자)을 사용합니다. ) 및 상수 사용 모두 대문자를 사용하고 단어를 밑줄로 구분하세요.

let myAge; // 변수: CamelCase 이름 지정 const PAGE_SIZE; // 상수: 모두 대문자, 단어를 구분하려면 밑줄을 사용하세요. function getAge() {} // 일반 함수: CamelCase 이름 지정 function Person() {} // 생성자: CamelCase naming

변수와 함수를 구별하기 위해서는 변수 이름 앞에는 이름을 붙여야 하고, 함수 이름 앞에는 동사를 붙여야 합니다(생성자 이름은 대개 명사입니다). 다음 예를 보세요.

let count = 10; // Goodlet getCount = 10; // Bad, look like functionfunction getName() {} // Goodfunction theName() {} // Bad, look like variable

네이밍은 과학일 뿐만 아니라 기술이기도 하지만 일반적으로 네이밍 길이는 최대한 짧아야 하며 요점을 포착해야 합니다. 변수 이름에 값의 데이터 유형을 반영하십시오. 예를 들어 count, length, size라는 이름은 데이터 유형이 숫자임을 나타내고, name, title, message라는 이름은 데이터 유형이 문자열임을 나타냅니다. 그러나 i, j, k와 같은 단일 문자로 명명된 변수는 일반적으로 루프에서 사용됩니다. 데이터 유형을 반영하는 이러한 이름을 사용하면 다른 사람이나 본인이 코드를 더 쉽게 읽을 수 있습니다.

foo, bar, tmp와 같은 의미 없는 이름을 사용하지 마세요. 함수 및 메서드 이름 지정의 경우 첫 번째 단어는 동사여야 합니다. 다음은 동사 사용에 대한 몇 가지 일반적인 규칙입니다.

동사 의미

can 함수는 부울 값을 반환합니다.

has 함수는 부울 값을 반환합니다.

is 함수는 부울 값을 반환합니다.

get 부울이 아닌 값을 반환하는 함수

set 값을 저장하는 데 사용되는 함수

1.3 직접 수량

JS中包含一些类型的原始值:字符串、数字、布尔值、null和undefined。同样也包含对象直接量和数组直接量。这其中,只有布尔值是自解释(self-explanatory)的,其他的类型或多或少都需要思考一下它们如何才能更精确地表示出来。

关于字符串:字符串可以用双引号也可以用单引号,不同的JS规范推荐都不同, 但切记不可在一个项目中混用单引号和双引号。

关于数字:记住两点建议:第一,为了避免歧义,请不要省略小数点之前或之后的数字;第二,大多数开发者对八进制格式并不熟悉,也很少用到,所以最好的做法是在代码中禁止八进制直接量。

// 不推荐的小数写法:没有小数部分let price = 10.;// 不推荐的小数写法:没有整数部分let price = .1;// 不推荐的写法:八进制写法已经被弃用了let num = 010;

关于null:null是一个特殊值,但我们常常误解它,将它和undefined搞混。在下列场景中应当使用null。

用来初始化一个变量,这个变量可能赋值为一个对象。

用来和一个已经初始化的变量比较,这个变量可以是也可以不是一个对象。

当函数的参数期望是对象时,用作参数传入。

当函数的返回值期望是对象时,用作返回值传出。

还有下面一些场景不应当使用null。

不要使用null来检测是否传入了某个参数。

不要用null来检测一个未初始化的变量。

理解null最好的方式是将它当做对象的占位符(placeholder)。这个规则在所有的主流编程规范中都没有提及,但对于全局可维护性来说至关重要。

关于undefined:undefined是一个特殊值,我们常常将它和null搞混。其中一个让人颇感困惑之处在于null == undefined结果是true。然而,这两个值的用途却各不相同。那些没有被初始化的变量都有一个初始值,即undefined,表示这个变量等待被赋值。比如:

let person; // 不好的写法console.log(person === undefined); // true

尽管这段代码能正常工作,但我建议避免在代码中使用undefined。这个值常常和返回"undefined"的typeof运算符混淆。事实上,typeof的行为也很让人费解,因为不管是值是undefined的变量还是未声明的变量,typeof运算结果都是"undefined"。比如:

// foo未被声明let person;console.log(typeof person); // "undefined"console.log(typeof foo); // "undefined"

这段代码中,person和foo都会导致typeof返回"undefined",哪怕person和foo在其他场景中的行为有天壤之别(在语句中使用foo会报错,而使用person则不会报错)。

通过禁止使用特殊值undefined,可以有效地确保只在一种情况下typeof才会返回"undefined":当变量为声明时。如果你使用了一个可能(或者可能不会)赋值为一个对象的变量时,则将其赋值为null。

// 好的做法let person = null;console.log(person === null); // true

将变量初始值赋值为null表明了这个变量的意图,它最终很可能赋值为对象。typeof运算符运算null的类型时返回"object", 这样就可以和undefined区分开了。

关于对象直接量和数组直接量: 请直接使用直接量语法来创建对象和数组,避免使用Object和Array构造函数来创建对象和数组。

1.4 注释

注释是代码中最常见的组成部分。它们是另一种形式的文档,也是程序员最后才舍得花时间去写的。但是,对于代码的总体可维护性而言,注释是非常重要的一环。JS支持两种注释:单行注释和多行注释。

很多人喜欢在双斜线后敲入一个空格,用来让注释文本有一定的偏移(我非常推荐你这么做)。单行注释有三种使用方法:

独占一行的注释,用来解释下一行代码。这行注释之前总是有一个空行,且缩进层级和下一行代码保持一致。

在代码行的尾部的注释。代码结束到注释之间至少有一个缩进。注释(包括之前的代码部分)不应当超过最大字符数限制,如果超过了,就将这条注释放置于当前代码行的上方。

被注释的大段代码(很多编辑器都可以批量注释掉多行代码)。

单行注释不应当以连续多行注释的形式出现,除非你注释掉一大段代码。只有当需要注释一段很长的文本时才使用多行注释。

虽然多行注释也可以用于注释单行,但是我还是推荐仅在需要使用多行注释的时候,才使用多行注释。多行注释一般用于以下场景:

模块、类、函数开头的注释

需要使用多行注释

我十分推荐你使用Java风格的多行注释,看起来十分美观,而且很多编辑器支持自动生成,见如下示例:

/**
 * Java风格的注释,注意*和注释之间
 * 有一个空格,并且*左边也有一个空格。
 * 你甚至可以加上一些@参数来说明一些东西。
 * 例如:
 *
 * @author 作者
 * @param Object person
 */

何时添加注释是程序员经常争论的一个话题。一个通行的指导原则是, 当代码不够清晰时添加注释,而当代码很明了时不应当添加注释。 基于这个原则,我推荐你在下面几种情况下添加注释:

难以理解的代码: 难以理解的代码通常都应当加注释。根据代码的用途,你可以用单行注释、多行注释,或者混用这两种注释。关键是让其他人更容易读懂这段代码。

可能被误认为错误的代码: 例如这段代码while(el && (el = el.next)) {}。在团队开发中,总是会有一些好心的开发者在编辑代码时发现他人的代码错误,就立即将它修复。有时这段代码并不是错误的源头,所以“修复”这个错误往往会制造其他错误,因此本次修改应当是可追踪的。当你写的代码有可能会被别的开发者认为有错误时,则需要添加注释。

浏览器特性hack: 这个写过前端的都知道,有时候你不得不写一些低效的、不雅的、彻头彻尾的肮脏代码,用来让低版本浏览器正常工作。

1.5 语句和表达式

关于 花括号的对齐方式 ,有两种主要的花括号对齐风格。第一种风格是,将左花括号放置在块语句中第一句代码的末尾,这种风格继承自Java;第二种风格是将左花括号放置于块语句首行的下一行,这种风格是随着C#流行起来的,因为Visual Studio强制使用这种对齐方式。当前并无主流的JS编程规范推荐这种风格,Google JS风格指南明确禁止这种用法,以免导致错误的分号自动插入。我个人也推荐使用第一种花括号对齐格式。

// 第一种花括号对齐风格if (condition) {
}// 第二种花括号对齐风格if (condition)
{
}

关于块语句间隔: 有下面三种风格,大部分的代码规范都推荐使用第二种风格:

// 第一种风格if(condition){
  doSomething();
}// 第二种风格if (condition) {
  doSomething();
}// 第三种风格if ( condition ) {
  doSomething();
}

关于switch语句,很多JS代码规范都没有对此做详细的规定,一个是而实际工作中你也会发现使用场景比较少。因为你只有在有很多条件判断的情况下才会用switch(短条件就直接用if语句了),但是熟练的程序员面对很多的判断条件一般都会用对象表查询来解决这个问题。看如下推荐的风格代码:

switch (condition) {  case 'cond1':  case 'cond2':
    doCond1();    break;  case 'cond3':
    doCond3();    break;  default:
    doDefault();
}

推荐你遵循如下的风格:

switch后的条件括号需要前后各一个空格;

case语句需要相对switch语句缩进一个层级;

允许多个case语句共用一个处理语句;

如果没有默认执行代码,可以不用加default

关于with:JS引擎和压缩工具无法对有with语句的代码进行优化,因为它们无法猜出代码的正确含义。在严格模式中,with语句是被明确禁止的,如果使用则报语法错误。这表明ECMAScript委员会确信with不应当继续使用。我也强烈推荐避免使用with语句。

关于for循环:for循环有两种,一种是传统的for循环,是JS从C和Java中继承而来,主要用于遍历数组成员;另外一种是for-in循环,用来遍历对象的属性。

针对for循环, 我推荐尽可能避免使用continue,但也没有理由完全禁止使用,它的使用应当根据代码可读性来决定。

for-in循环是用来遍历对象属性的。不用定义任何控制条件,循环将会有条不紊地遍历每个对象属性,并返回属性名而不是值。for-in循环有一个问题,就是它不仅遍历对象的实例属性(instance property),同样还遍历从原型继承来的属性。当遍历自定义对象的属性时,往往会因为意外的结果而终止。出于这个原因,最好使用hasOwnProperty()方法来为for-in循环过滤出实例属性。我也推荐你这么做,除非你确实想要去遍历对象的原型链,这个时候你应该加上注释说明一下。

// 包含对原型链的遍历for (let prop in obj) {  console.log(`key: ${prop}; value: ${obj[prop]}`);
}for (let prop in obj) {  if (obj.hasOwnProperty(prop)) {    console.log(`key: ${prop}; value: ${obj[prop]}`);
  }
}

关于for-in循环,还有一点需要注意,即for-in循环是用来遍历对象的。一个常见的错误用法是使用for-in循环来遍历数组成员,它的结果可能不是你想要的(得到的是数组下标),你应该使用ES6的for-of循环来遍历数组。

let arr = ['a', 'b', 'c'];for (let i in arr) {  console.log(i); // 0, 1, 2}for (let v of arr) {  console.log(v); // 'a', 'b', 'c'}

1.6 变量声明

我们知道JS中var声明的变量存在变量提升,对变量提升不熟悉的同学写代码的时候就会产生不可意料的Bug。例如:

function func () {  var result = 10 + result;  var value = 10;  return result; // return NaN}// 实际被解释成function func () {  var result;  var value;
  result = 10 + result;
  value = 10;  return result;
}

在某些场景中,开发者往往会漏掉变量提升,for语句就是其中一个常见的例子(因为ES5之前没有块级作用域):

function func (arr) {  for (var i = 0, len = arr.length; i < len; i += 1) {}
}// 实际被解释成function func (arr) {  var i, len;  for (i = 0, len = arr.length; i < len; i += 1) {}
}

变量声明提前意味着:在函数内部任意地方定义变量和在函数顶部定义变量是完全一样的。 因此,一种流行的风格是将你所有变量声明放在函数顶部而不是散落在各个角落。简言之,依照这种风格写出的代码逻辑和JS引擎解析这段代码的习惯是非常相似的。我也建议你总是将局部变量的定义作为函数内第一条语句。

function func (arr) {  var i, len;  var value = 10;  var result = value + 10;  for (i = 0; len = arr.length; i < len; i += 1) {    console.log(arr[i]);
  }
}

当然,如果你有机会使用ES6,那我强烈推荐你完全抛弃var,直接用let和const来定义变量。相信我,抛弃var绝对值得的,let和const提供了块级作用域,比var更安全可靠,行为更可预测。

1.7 函数声明与调用

和变量声明一样,函数声明也会被JS引擎提升。因此,在代码中函数的调用可以出现在函数声明之前。但是,我们推荐总是先声明JS函数然后使用函数。此外,函数声明不应当出现在语句块之内。例如,这段代码就不会按照我们的意图来执行:

// 不好的写法if (condition) {  function func () {
    alert("Hi!");
  }
} else {  function func () {
    alert("Yo!");
  }
}

这段代码在不同浏览器中的运行结果也是不尽相同的。不管condition的计算结果如何,大多数浏览器都会自动使用第二个声明。而Firefox则根据condition的计算结果选用合适的函数声明。这种场景是ECMAScript的一个灰色地带,应当尽可能地避免。函数声明应当在条件语句的外部使用。这种模式也是Google的JS风格指南明确禁止的。

一般情况下,对于函数调用写法推荐的风格是,在函数名和左括号之间没有空格。这样做是为了将它和块语句区分开发。

// 好的写法callFunc(params);// 不好的写法,看起来像一个块语句callFunc (params);// 用来做对比的块语句while (condition) {}

1.8 立即调用的函数

IIFE(Immediately Invoked Function Expression),意为立即调用的函数表达式,也就是说,声明函数的同时立即调用这个函数。ES6中很少使用了,因为有模块机制,而IIFE最主要的用途就是来模拟模块隔离作用域的。下面有一些推荐的IIFE写法:

// 不好的写法:会让人误以为将一个匿名函数赋值给了这个变量var value = function () {  return {    msg: &#39;Hi&#39;
  };
}();// 为了让IIFE能够被一眼看出来,可以将函数用一对圆括号包裹起来// 好的写法var value = (function () {  return {    msg: &#39;Hi&#39;
  };
}());// 好的写法var value = (function () {  return {    msg: &#39;Hi&#39;
  };
})();

1.9 严格模式

如果你在写ES5代码,推荐总是使用严格模式。不推荐使用全局的严格模式,可能会导致老的代码报错。推荐使用函数级别的严格模式,或者在IIFE中使用严格模式。

1.10 相等

关于JS的强制类型转换机制,我们不得不承认它确实很复杂,很难全部记住(主要是懒)。所以我推荐你,任何情况下,做相等比较请用===和!==。

1.11 eval

动态执行JS字符串可不是一个好主意,在下面几种情况中,都可以动态执行JS,我建议你应该避免这么做,除非你精通JS,并且知道自己在做什么。

eval("alert(&#39;bad&#39;)");const func = new Function("alert bad(&#39;bad&#39;)");
setTimeout("alert(&#39;bad&#39;)", 1000);
setInterval("alert(&#39;bad&#39;)", 1000);

1.12 原始包装类型

JS装箱和拆箱了解下,原始值是没有属性和方法的,当我们调用一个字符串的方法时,JS引擎会自动把原始值装箱成一个对象,然后调用这个对象的方法。但这并不意味着你应该使用原始包装类型来创建对应的原始值,因为开发者的思路常常会在对象和原始值之间跳来跳去,这样会增加出bug的概率,从而使开发者陷入困惑。你也没有理由自己手动创建这些对象。

// 自动装箱const name = &#39;Nicholas&#39;;console.log(name.toUpperCase());// 好的写法const name = &#39;Nicholas&#39;;const author = true;const count = 10;// 不好的写法const name = new String(&#39;Nicholas&#39;);const author = new String(true);const count = new Number(10);

1.13 工具

团队开发中,为了保持风格的统一,Lint工具必不可少。因为即使大家都明白要遵守统一的编程风格,但是写代码的时候总是不经意就违背风格指南的规定了(毕竟人是会犯错的)。这里我推荐你使用ESLint工具进行代码的风格检查,你没必要完全重新写配置规则,你可以继承已有的业内优秀的JS编码规范来针对你团队做微调。我这里推荐继承自Airbnb JavaScript Style Guide,当然,你也可以继承官方推荐的配置或者Google的JS编码风格,其实在编码风格上,三者在大部分的规则上是相同的,只是在一部分细节上不一致而已。

当然,如果你实在是太懒了,那了解一下JavaScript Standard Style,它是基于ESLint的一个JS风格检查工具,有自己的一套风格,强制你必须遵守。可配置性没有直接引入ESLint那么强,如果你很懒并且能够接受它推荐的风格,那使用StandardJS倒也无妨。

相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!

推荐阅读:

使用JS实做出加密解密操作

js 数组操作与解析方法汇总

위 내용은 사용자 정의 및 유지 관리가 가능한 JS 코드를 작성하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.