이 첫 번째 기사에서는 NodeJ의 프로그래밍 세부 사항에 대해 이야기해 보겠습니다.
1. 배열 탐색
for (var i=0, l=arr.length; i<l; i++)
이 방식으로 작성하면 각 루프에서 배열 객체의 길이를 얻는 데 한 단계가 절약된다는 장점이 있습니다. 배열 길이가 길수록 값이 더 분명해집니다.
2. 변수가 참인지 거짓인지 확인
if (a) {...} //a='', a='0', a=[], a={}
if 조건부 판단의 결과는 false, true, true, true입니다. 이 결과는 PHP의 결과와 다르므로 혼동하지 마십시오. 비동일성 판단과 유사한 상황도 구별할 필요가 있다.
3. 0값의 불일치 판정
1 if (0 == '0') {...} //true 2 if (0 == []) {...} //true 3 if (0 == [0]) {...} //true 4 if (0 == {}) {...} //false 5 if (0 == null) {...} //false 6 if (0 == undefined) {...} //false
사실 이런 이상한 판단이 많이 있는데, 흔한 것들만 나열해봤습니다. 규칙을 이해하려면 내 다른 블로그 게시물인 [JavaScript] JavaScript의 관계 연산 및 if 문에 대한 심층 분석을 참조하세요.
4.parseInt의 함정
var n = parseInt(s); //s='010'
이 명령문이 실행된 후 n의 값은 10이 아닌 8이 됩니다. 많은 분들이 알고 계시지만 프로그래밍에서는 실수가 불가피하다는 사실을 저도 잘 알고 있습니다. 그러므로 다음과 같이 작성하는 것이 가장 좋으며 실수하지 않을 것입니다.
var n = parseInt(s, 10);
5. 변수는 사용하기 전에 선언해야 합니다
변수를 선언하지 않고 직접 사용하면 오류가 없지만 이렇게 작성하면 오류가 발생하기 쉽습니다. 인터프리터는 이를 전역 변수로 해석하기 때문에 다른 전역 변수와 이름이 동일하여 오류가 발생할 수 있습니다. 그러므로 변수를 사용하기 전에 먼저 선언하는 습관을 길러야 합니다.
6. 루프에 비동기 상황이 있습니다
for (var i=0, l=arr.length; i<l; i++) { var sql = "select * from nx_user"; db.query(sql, function(){ sys.log(i + ': ' + sql); }); //db.query为表查询操作,是异步操作 }
출력 결과는 동일하며 i=arr.length-1일 때 출력 내용임을 알 수 있습니다. JavaScript는 단일 스레드이기 때문에 비동기 작업을 실행하기 전에 먼저 전체 루프의 동기 콘텐츠를 실행합니다. 코드의 익명 콜백 함수는 비동기 콜백입니다. 이 함수가 실행되면 for 루프와 일부 후속 동기화 작업이 완료됩니다. 폐쇄 원칙으로 인해 이 함수는 for 루프의 마지막 루프에서 sql 변수와 i 변수의 내용을 유지하므로 잘못된 결과가 발생합니다.
그럼 우리는 어떻게 해야 할까요? 하나는 다음과 같이 즉시 기능을 사용하는 것입니다.
for (var i=0, l=arr.length; i<l; i++) { var sql = "select * from nx_user"; (function(sql, i){ db.query(sql, function(){ sys.log(i + ': ' + sql); }); //db.query为表查询操作,是异步操作 })(sql, i); }
또 다른 방법은 비동기 작업 부분을 추출하여 다음과 같이 함수를 작성하는 것입니다.
var outputSQL = function(sql, i){ db.query(sql, function(){ sys.log(i + ': ' + sql); }); //db.query为表查询操作,是异步操作 } for (var i=0, l=arr.length; i<l; i++) { var sql = "select * from nx_user"; outputSQL(sql, i); }
7. 대용량 데이터를 처리할 때는 중첩 루프를 피하세요.
중첩 루프의 처리 시간은 데이터 양이 늘어날수록 기하급수적으로 늘어나기 때문에 최대한 피해야 합니다. 이런 상황에서 더 좋은 방법이 없다면 공간을 시간과 맞바꾸는 것이 일반적인 전략, 즉 보조 순환 데이터의 해시 매핑 테이블을 구축하는 것이다. 물론, 구체적인 상황은 사례별로 분석되어야 합니다. 언급할 또 다른 점은 Array.sort()(이 메서드는 두 개의 루프 계층을 사용하여 구현해야 함)와 같은 일부 메서드 자체가 루프 본문이므로 사용할 때 주의해야 한다는 것입니다.
8. 재귀 호출을 피하세요.
재귀 호출의 장점은 코드가 간결하고 구현이 간단하다는 점이지만, 단점이 매우 중요하므로 설명하면 다음과 같습니다.
(1) 함수 스택의 크기는 재귀 수준에 따라 선형적으로 증가하며, 함수 스택에는 재귀 수준이 특정 수에 도달하면 함수 스택이 오버플로되어 프로그램 오류가 발생합니다. 🎜>
(2) 각 재귀 레벨에는 추가 스택 푸시 및 팝 작업이 추가됩니다. 즉, 함수 호출 중에 장면을 저장하고 장면을 복원합니다.따라서 재귀 호출은 최대한 피해야 합니다.
9. 모듈 파일의 범위 격리에 관해.
Node가 JavaScript 모듈 파일을 컴파일할 때 해당 내용은 다음과 같이 헤드와 테일로 패키징됩니다.
(function(exports, require, module, __filename, __dirname){ 你的JavaScript文件代码 });
(function(){ ... ... })();
다음은 오류 코드의 예입니다.
var o = []; o['name'] = 'LiMing';
var o = []; o['name'] = 'LiMing'; var s = JSON.stringify(o);
원래는 객체 o의 name 속성이 JSON 문자열에 있을 거라고 생각했는데, 결과는 그렇지 않았습니다. 저도 당시에 많이 놀랐는데, 배열과 객체를 섞는 문제인 줄 직감해서 시도해 봤는데 문제였습니다. 나중에 ECMA 사양에서 배열이 JA 규칙에 따라 직렬화된다는 것을 알게 되었습니다. 그러므로 좋은 프로그래밍 습관을 기르고 배열과 객체를 올바르게 사용하며 혼합하지 않는 것이 필요합니다.
11. 우아한 약속 프로그래밍
nodeJ를 접해본 사람이라면 누구나 이런 경험을 했을 것이라고 생각합니다. 비동기 콜백이 비동기 콜백 내에 중첩되면 코드가 혼란스러워지고 가독성이 떨어집니다. nodeJ의 이러한 딜레마는 promise의 도움으로 극복될 수 있습니다. 약속은 조각가와 같아서 당신의 코드를 우아하고 아름답게 만들어줍니다. Promise에는 A 사양이 있으며 온라인에는 여러 가지 구현 방법이 있으므로 참조할 수 있습니다.