구문과 동작 방식에 있어 자바스크립트 만이 지니는 예외적 사례와 특징
자바스크립트는 동적 인터프리터 프로그래밍 언어이므로 다른 전통적 객체지향 프로그래밍 언어들과 구문이 다름
시간 및 알고리즘 공간 복잡도 분석을 위한 빅오 표기법 개념
시간(실행시간)과 공간(사용된 메모리) 관점에서 알고리즘 구현을 분석하는 법 이해
- 범위(scope)는 자바스크립트 변수에 대한 접근 권한을 정의
- 자바스크립트에서 변수는 전역범위 또는 지역 범위에 속함
- 자바스크립트에서 연산자 없이 변수를 선언 가능
test = "sss"; console.log(test); // prints "sss"
- 위와 코드는 전역 변수를 생성하지만 위 선언 방식은 가장 안좋은 사용법 중 하나
- var, let을 사용해 변수를 선언, 수정하지 않는 변수 선언 시 const로 선언
- var는 변수 선언하는데 사용되는 키워드로 어디에서 선언하든 변수 선언이 함수의 맨 앞으로 이동하는데 이를 호이스팅이라도 함
- 스크립트 실행 시 변수가 스크립트 가장 마지막에 선언되어도 선언 코드가 가장 마지막에 실행되는 게 아님
function scope1(){ var top = "top"; bottom = "bottom"; console.log(bottom); var bottom; } scope1(); // prints "bottom" - no error // 실제 동작하는 방식 function scope1(){ var top = "top"; var bottom; bottom = "bottom"; console.log(bottom); } scope1(); // prints "bottom" - no error
- scope1() 함수 가장 마지막 줄 위치한 bottom 변수 선언이 맨 앞으로 이동해 변수 출력은 오류 없이 수행
- 즉 var 키워드는 변수 범위가 가장 가까운 함수 범위라는 것을 의미한다
function scope2(print) { if (print) { var insideIf = '12'; } console.log(insideIf); } scope2(true); // prints '12' - no error // 실제 동작하는 방식 function scope2(print) { var insideIf; if (print) { insideIf = '12'; } console.log(insideIf); } scope2(true); // prints '12' - no error
- scope2 함수는 insideIf 변수와 가장 가까운 함수 범위
- 자바에선 위 구문은 오류를 일으키는데 insideIf 변수가 if문 블록 내에서만 사용 가능하고 if문 블록 외부에선 사용할 수 없기 때문
var a = 1 function four() { if (true) { var a = 4; } console.log(a); // prints '4' } four();
- 전역변수 값인 1이 아닌 4가 출력되는 건 a 변수가 four 함수 내 재선언되어 사용 가능하기 때문
function scope3(print) { if (print) { let insideIf = '12'; } console.log(insideIf); } scope3(true); // prints ''
- 콘솔에 아무것도 출력되지 않는 이유는 insideIf 변수가 if문 블록 내에서만 사용 가능하기에
--
- 자바스크립트엔 boolean, number, string, undefined, object, function, symbol과 같은 7개의 기본 자료형 존재
- 특이한 점은 선언만 되고 값이 할당되지 않은 변수엔 undefined가 할당 된다는
var is20 = false; // boolean typeof is20; // boolean var age = 19; typeof age; // number var lastName = "Bae"; typeof lastName; // string var fruits = ["Apple", "Banana", "Kiwi"]; typeof fruits; // object var me = {firstName:"Sammie", lastName:"Bae"}; typeof me; // object var nullVar = null; typeof nullVar; // object var function1 = function(){ console.log(1); } typeof function1 // function var blank; typeof blank; // undefined
- if문 내에 참/거짓 확인 사용되는데 많은 언어의 경우 if()함수 내 매개변수는 boolean 형이어야하지만 자바스크립트는 더 유연하다
if (node) { }
- node는 변수로 변수가 비거나 null 또는 undefined면 해당 변수는 false로 평가
- 다음은 false로 평가되는 경우
- false
- 0
- 빈 문자열
- NaN
- undefined
- null
- 다음은 true로 평가되는 경우
- true
- 0이 아닌 다른 숫자
- 비어있지 않은 문자열
- 비어있지 않은 객체
var printIfTrue = ''; if (printIfTrue) { console.log('truthy'); } else { console.log('falsey'); // prints 'falsey' }
- 자바스크립트는 스크립트 언어로 변수 선언 시 변수에 형이 할당되지 않고 대신 코드가 실행 될 때 해당 변수의 형이 해석
- 따라서 ===는 ==보다 등가(양쪽이 같은지 여부)를 더 엄격히 확인
- ==가 값만 확인하는 반면 ===는 형과 값 모두 확인
"5" == 5 // returns true "5" === 5 // returns false
- "5" == 5 는 true를 반환하는데 "5"가 비교 전 숫자로 강제 변환 되기 때문이고 반면 "5" == 5는 문자열과 숫자 타입까지 비교해 false를 반환
- 자바와 같은 강 자료형 언어는 isEquals()를 사용해 두 객체가 동일한지 확인하나 자바스크립트에선 두 객체가 동일한지 확인하고자 == 연산자를 써도 true로 평가되지 않는다
var o1 = {}; var o2 = {}; o1 == o2 // returns false o1 === o2 // returns false
- 위 객체는 동일(동일한 속성과 값을 지님)함에도 두 객체는 동일하지 않은데 두 변수의 메모리상 주소가 다르기 때문
- 이것이 자바스크립트 애플리케이션 lodash나 underscore와 같은 유틸리티 라이브러리를 사용하는 이유로 두 라이브러리엔 두 객체 혹은 두 값을 정확히 확인할 수 있는 isEqual 함수가 존재
- isEqual 함수가 속성 기반 등가 비교 방식으로 구현되어 객체의 각 속성을 비교
function isEquivalent(a, b) { // arrays of property names var aProps = Object.getOwnPropertyNames(a); var bProps = Object.getOwnPropertyNames(b); // If their property lengths are different, they're different objects if (aProps.length != bProps.length) { return false; } for (var i = 0; i < aProps.length; i++) { var propName = aProps[i]; // If the values of the property are different, not equal if (a[propName] !== b[propName]) { return false; } } // If everything matched, correct return true; } isEquivalent({'hi':12},{'hi':12}); // returns true
- isEquivalent 함수는 문자열이나 숫자 하나만을 속성으로 갖는 객체에 대해서 도 잘 동작
var obj1 = {'prop1': 'test','prop2': function (){} }; var obj2 = {'prop1': 'test','prop2': function (){} }; isEquivalent(obj1,obj2); // returns false
- 위 처럼 isEquivalent 함수가 잘 동작하는 이유는 함수와 배열이 등가 비교를 위해 단순히 == 연산자를 사용하는 것이 아니기 때문
var function1 = function(){console.log(2)}; var function2 = function(){console.log(2)}; console.log(function1 == function2); // prints 'false'
- 두 함수가 동일한 연산을 수행하지만 두 함수의 메모리상 주소는 다르기에 등가 연산자는 false를 반환
- 기본 등가 확인 연산자인 ==와 ===는 문자열과 숫자에만 사용 가능하며 객체에 대한 등가 확인을 구현 하려면 객체의 각 속성 확인해야함
- 자바스크립트엔 대부분 프로그래밍 언어들이 사용하지 않는 다른 방식의 변수 선언 방식 존재
- var는 함수 범위 내 변수 선언
- let은 블록 범위에서 변수 선언하고 아무 연산자 없이 변수 선언하면 해당 변수는 전역 범위에서 선언 됌(전역 범위로 변수 선언하는 것은 피해야함)
- 형 확인 위해 typeof를 사용해 원하는 형이 맞는지 검증 가능
- 등가 확인 위해 값에 대해선 == 사용 값과 형 모두 같은지 확인하기 위해 === 사용하나 ==와 ===는 숫자, 문자열, 불리언 같은 비객체형만 사용 가능