Developer/자바스크립트

자바스크립트, 변수와 함수,엄격모드, 자료표현양식

단님 2024. 5. 31. 01:15
728x90
변수 선언

let, const, var구문을 이용한 변수의 선언

 

호이스팅( Hoisting )의 의미

 

호이스팅이란 컴파일 과정에서 선언 및 정의 위치와 관계 없이

변수나 함수의 선언 및 정의부를 코드의 최상단으로 끌어 올리는 것을 의미하는데,

변수나 함수의 선언은 컴파일 단계에서 메모리에 저장되지만 실제 물리적 코드의 위치가 변경되어 저장되는 것은 아님.

 

스코프( Scope ) (범위를 말함.)

 

  • 함수 스코프( var구문 )

- 함수 외부에서 선언된 변수는 전역변수

함수 내부에서 선언된 변수만 지역변수로 인식하여,

일반적인 블럭 스코프에서는 전역 변수로 인식.

  • 블럭 스코프( let, const구문 )

- 변수가 선언된 블럭, 구문, 표현식 내에서 유효한 범위를 가지는 지역변수로 인식되며, var과 달리 중복 선언 불가.

블럭 바깥에서는 선언된 시점이후의 소스 코드 전체에 유효한 전역변수 성격을 가져 var구문과 동일하게 작동.

 

console.log(n1);    
n1 = 5;             

var n1;             // var Hoisting : 변수의 선언부만 호이스팅.

n1은 정의되지 않았으므로 ReferenceError(n1 is not defined)가 발생되어야 함에도

아래 var로 선언된 n1에 대한 var hoisting으로 인해 undefined값 반환.

 

{
    var n3 = 15;       
}

블럭 내부에 선언된 var는 함수 내에서만 지역적인 성격을 띄며

블럭에는 영향을 받지 않아 블럭을 무시하고 전연 변수로 인식.

 

function varTest() {    
    var n2 = 10;      
}

var는 함수 스코프(Function Scope)로써 블럭 스코프와 관계없이

함수 외부 또는 내부로 구분짓는 전역과 지역 변수로 나뉨.

 

var n4 = 20;
var n4 = 30;

var은 이와같이 중복선언도 가능.

 

이와 같이 var를 봐서 알 수 있었듯,

유연한 코딩이 가능하지만 코드에 안정성을 저하시키는 요인이 될 수 있으므로,

특수한 경우를 제외하고서는 사용을 되도록 지양하자.

 

let n1 = 5;            
// let n1 = 5;         
console.log(n1);

let : 선언된 시점부터 접근이 가능하며 블럭 스코프가 적용되어

블럭 외부 또는 내부를 기준으로 하여 전역과 지역으로 나뉨.

var과 같이 중복 선언 불가.

 

function letTest() {
    let n2 = 10; 
}
// console.log(n2);

n2 는 지역변수 임으로 바깥에서 찾지못함.

 

{
    let n3 = 15;  
}
// console.log(n3);

n3 는 지역변수 임으로 바깥에서 찾지 못함.

 

const n4 = 8;         
// n4 = 9;

변수에 대한 값부 변경 불가.(immutable)

 


' use strict '

 

자바스크립트는 기본적으로 별도의 변수 타입을 구분하지 않아

변수 선언 시 let, const, var과 같은 구문 생략이 가능한 묵시적 변수 선언이 가능함으로써

유연하고 빠른 프로그래밍이 가능 하지만, 이는 프로그램의 안정성 측면에서는 상당한 리스크를 수반.

따라서 프로그램의 안정성과 좀 더 나은 성능 향상을 위해서 엄격모드(strict mode) 사용을 권장.

 

사용방법 , 'use strict'

이와 같이 전역적으로 선두에 선언되어야 적용되며, 코드의 중간에 선언되는 것은 적용되지 않음

 

 


함수선언
function 함수명(){}
function test() {       // 함수의 선언 형식 : function 함수명() {  실행블럭; }

    // 'use strict';    // 함수에 이와 같이 지역적으로 엄격모드 선언 가능. 단, 이 때에도 전역적
    /*                     으로 선언할 때와 마찬가지로 함수의 선두에 선언되어야만 적용.      */
    n2 = 30;

}
// console.log(n2);     
test();                 
console.log(n2);

비엄격 모드에서의 묵시적 변수 선언.

함수 외부에서 바로 참조는 안되나 , 함수 호출을 통해 전역변수처럼 참조는 가능함.


 

자료 표현 양식

 

 boolean : null, NaN(Not a Number), Undefined, ""(빈문자열), 0 은

false와 같진 않지만 조건식이나 산술 연산 시 상호 변환하여 평가 가능하며,

그 외의 값에 대해서는 연산 시 true로 변환하여 평가 가능.

논리 연산자 !(not)을 이용하여 확인 가능.

 

undefined : 값을 할당하지 않은 변수(미 초기화)는 브라우저가 undefined값 할당.

또한 명시적 반환(return)을 하지않는 함수도 undefined값을 반환.

 

null : null은 사용자가 명시적으로 할당.

 

bigint : number보다 더 큰 정수를 표현하기 위한 타입. 숫자 상수에 접미사 n을 붙여 표현.

 

symbol :  열거형과 유사한 고유한 식별자로써의 기능을 담당하며

객체의 속성 key값으로도 사용 가능.

다른 래퍼(Wrapper) 객체와는 달리 new연산자를 통한 Symbol객체 생성은 불가.

 

const symbol1 = Symbol('enum');         
const symbol2 = Symbol('enum');
const symbol3 = Symbol.for('enum');    
const symbol4 = Symbol.for('enum');

고유 식별자 생성. 자바의 new String("문자열")과 유사하다.

symbol.for() : 고유한 심볼을 생성하되 , 전역의 식별자들을 검색하여

기존과 동일한 symbol.for 이 있을경우 동일한 참조를 반환한다.

console.log(symbol1 === 'enum');    // false
console.log(symbol1 === symbol2);   // false
console.log(symbol1 === symbol3);   // false
console.log(symbol3 === symbol4);   // true

마지막이 true 인 이유는 symbol 3 저장된것을 꺼내 참조하여 4에 저장하였기 때문에 같다고 볼 수 있겠다.

console.log(symbol1);               // Symbol(enum)
console.log(symbol1.toString());    // Symbol(enum)
console.log(symbol1.description);   // enum

description 메서드는 내부에 있는 것을 꺼내 표현해준다.

alert(symbol1.toString());         

alert(symbol1.description);

toString : 자바스크립트 최상위 객체인 Object로부터 자동 상속되는 메서드로

기본적으로 객체에 대한 정보를 문자열로 반환. 자바와 거의 유사.

description : description속성을 이용하여 심볼값 자체에 대한 문자열 반환.

 

심볼은 항상 문자열로 자동 변환되어 반환되지 않음에 주의.

문자열을 확인해야 할 경우 위와같이 toString 또는 description 을 이용하자.

 

변수의 자료형

 

자바스크립트에서 변수의 타입은 느슨한 타입(loosely typed) 또는 동적 타입(dynamic typed)이 적용되어

별도의 변수의 타입을 구분하지 않으며 대입되는 값에 의해 그 타입이 동적으로 결정.

따라서 하나의 변수에 여러 타입의 값을 저장 가능

 

래퍼 객체(Wrapper Object)

 

number, string, boolean, symbol, bigint등의 원시 타입의 값을 감싸는 형태

각각의 데이터 타입에 대응하는 Number, String, Boolean, Symbol , BigInt등의 객체가 제공되어

원시 값에 대한 체이닝(Chaining) 연산자(멤버연산자) .를 통한 속성(Property)이나 메서드에 접근 시

자동으로 생성되어 참조가 끝나면 소멸.

console.log('string'.charAt(5));

원시 값에 대한 속성 또는 메서드로 접근시 자동으로 래퍼 객체 생성.

 

Number
래퍼 객체로 숫자 형태의 문자열 값을 숫자 타입으로 변환한 참조 및 값을 반환.

 

형태 : new Number( 숫자 형태의 문자열 ) 또는 Number( 숫자 형태의 문자열 )

 

const n1 = new Number('5');

Number 객체의 참조 반환.

const n2 = Number('5');

함수 호출을 통한 형변환된 값을 직접 반환.

console.log(n1 + 5);

Number객체(n1)에 대한 산술 연산을 적용하여 자동 언박싱된 number로 변환되어 연산 처리됨.

 

console.log(n1 == 5);     // true
console.log(n2 == 5);     // true

console.log(n1 === 5);    // false
console.log(n2 === 5);    // true

console.log(typeof n1);   // object    
console.log(typeof n2);   // number

n1 과 n2 의 타입이 달라 값과타입체크(===) 에서 아님을 확인 가능.

typeof 연산자 : typeof 연산자 우변에 타입 측정 대상을 명시함으로써 문자열 형태로 타입 정보를 반환.

 

const n3 = new Number('a');   // NaN 저장.
const n4 = Number('a');       // NaN 반환.

console.log(n3); //[number : NaN]
console.log(n4); // NaN

인수 값이 숫자 형태가 아닌 경우에는  객체인 n3 는 NaN 저장, 함수인 n4는 NaN 반환한다.

 

Number 연산
const n5 = '8';
const n6 = '10';

console.log(n5 + n6);   //810
console.log(Number(n5) + n6);  //810

console.log(Number(n5) + Number(n6)); //18

n5는 number타입으로 변환되었지만 문자열(n6)에 대한 + 연산자에 의해 결과적으로 문자열 결합 연산 적용.

숫자 + 문자의 결합으로 인한 문자열로의 확장.

 

NaN 특성과 타입체크 주의

1. NaN 과 NaN 은 다르다 !

console.log(NaN === NaN); //false

 

2. NaN 의 타입체크시 number 타입의 0 으로 형변환됨 !

console.log(typeof NaN);

 

3. 이게 뭐람 ?

console.log(typeof +'1234' === 'number');
console.log(typeof +'string' === 'number');

문자열에 부호(+) 연산을 적용하였으므로 결과는 typeof +string 자체가 연산이 되면서 NaN ===number

NaN으로 평가되지만 다시 typeof연산자를 적용함으로써 0으로 변환 연산이 적용된 상태에서

타입평가를 함으로써 비교 연산의 결과는 true가 반환.

 

4.NaN 은 isNaN 이니 ? [ isNaN : 인수의 대상이 NaN인지의 여부를 평가하여 boolean값 반환.]

console.log(isNaN(NaN));

 

5.이건 또 뭐람 ?

console.log(Number(undefined)); //NaN

undefined는 비교 연산 시 false로 평가되지만 number 형식으로 변환은 불가.

 

6. null,true,false ?

console.log(Number(null));        // 0
console.log(Number(true));        // 1
console.log(Number(false));       // 0

 

7. 공백은 무엇...

console.log(Number('  123  '));   // 양쪽 끝의 공백을 제거한 후 변환된 number타입 값으로 반환.
console.log(Number('  12 3  '));  // 양쪽 끝이 아닌 중간에 공백이나 숫자 형태가 아닌 값이 포함된
//                                // 경우, 변환에 실패하여 NaN 반환.
console.log(Number('  '));        //공백이나 빈문자열은 0으로 변환

 

 

 

isNaN ?
isNaN(NaN); // 참
isNaN(undefined); // 참
isNaN({}); // 참

isNaN(true); // 거짓
isNaN(null); // 거짓
isNaN(37); // 거짓

// 문자열
isNaN("37"); // 거짓: "37"은 NaN이 아닌 숫자 37로 변환됩니다
isNaN("37.37"); // 거짓: "37.37"은 NaN이 아닌 숫자 37.37로 변환됩니다
isNaN("123ABC"); // 참: parseInt("123ABC")는 123이지만 Number("123ABC")는 NaN입니다
isNaN(""); // 거짓: 빈 문자열은 NaN이 아닌 0으로 변환됩니다
isNaN(" "); // 거짓: 공백이 있는 문자열은 NaN이 아닌 0으로 변환됩니다

// dates
isNaN(new Date()); // 거짓
isNaN(new Date().toString()); // 참

// 이것이 허위 양성이고 isNaN이 완전히 신뢰할 수 없는 이유이다.
isNaN("blabla"); // 참: "blabla"는 숫자로 변환됩니다.
// 이것을 숫자로 parsing 하는 것을 실패하고 NaN을 반환한다.

https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/isNaN 참조

 

undefined
찾을 수 없어 !

undefined는 전역 객체의 속성이다. 즉 전역 범위에서의 변수.

최신 브라우저에서 undefined는 설정 불가, 쓰기 불가한 속성.

그렇지 않더라도 덮어쓰는건 피하는게 좋다.

값을 할당하지 않은 변수 undefined 자료형.

메서드나 선언도 평가할 변수가 값을 할당받지 않은 경우 undefined를 반환.

함수는 값을 명시적으로 반환하지 않으면 undefined를 반환.

let x;
if (x === undefined) {
  // 이 문이 실행됨
} else {
  // 이 문이 실행되지 않음
}

 

let x;
if (typeof x === "undefined") {
  // 이 문이 실행됨
}

 

// x를 선언한 적 없음
// 오류 없이 true로 평가
if (typeof x === "undefined") {
  // 이 문이 실행됨
}

// ReferenceError 발생
if (x === undefined) {
}
null
비어있다 !

 

 JavaScript의 원시 값 중 하나로, 어떤 값이 의도적으로 비어있음을 표현.

 불리언 연산에서는 거짓으로 취급.

null 또는 undefined를 검사할 때, 동등 연산자(==)와 일치 연산자(===)의 차이를 주의.

typeof null; // "object" (하위호환 유지를 위해 "null"이 아님)
typeof undefined; // "undefined"
null === undefined; // false
null == undefined; // true
null === null; // true
null == null; // true
!null; // true
isNaN(1 + null); // false
isNaN(1 + undefined); // true