JABASCRIPT BASIC

변수

scope

function test(){
  var message = "hi"; // 지역변수
}
test();
alert(message); // 오류 발생
VM3067:5 Uncaught ReferenceError: message is not defined
    at <anonymous>:5:7

var 연산자는 변수를 로컬 스코프에서 정의한다는 점을 반드시 기억해야한다. var 키워드를 써서 변수를 정의하면 해당 변수는 위와 같이 함수가 종료되는 순간 파괴된다.

function test(){
  message = "hi"; // 전역변수
}
test();
alert(message);    //"hi"

var 연산자를 생략하는 경우에는 변수를 전역으로 정의할 수 있다.

데이터 타입 ECMAScript에는 다섯 가지 기본적인 데이터 타입이 있다. 이를 primitive(원시) 데이터 타입이라 부르기도한다.

  • Undefined

  • Null

  • Boolean

  • number

  • string

복잡한 데이터 타입

  • object : 함수를 제외한 객체 or null

  • function : 함수

위의 다섯 가지가 이에 해당된다.

undefined

undefinedvar 를 써서 변수를 정의했지만 초기화 하지않은 경우이다.

var message;
console.log(message); //=> undefined

기본적으로 초기화하지 않은 변수에는 항상 undefined가 할당된다.

var message; // undefined

console.log(message); // "undefined"
console.log(age);            // 오류
Uncaught ReferenceError: age is not defined
    at <anonymous>:1:13

undefined 값이 할당된 변수와 정의되지 않은 변수를 구분할 수 있어야한다. 아직 정의한 적 없는 변수에 실행할 수 있는 조적은 typeof뿐이다.

var message; 
typeof message
"undefined"
typeof age; // "undefined"

Null

Null 타입 역시 값 하나만을 갖는다. null 은 빈 객체를 가리키는 포인터이므로 typeof 를 호출하면 object를 반환한다.

var a = null;
typeof(a); // "object"

변수 정의시에 해당 변수가 객체를 가리키게 할 것이라면 null로 초기화하는 것을 권장한다.

console.log(null == undefined) // true

undefinednull에서 파생했으므로 표면적으로 동일한 것으로 정의한다. nullundefined는 서로 관련있지만 두 값은 아주 다르게 쓰인다. 변수값에 명시적으로 undefined를 할당해서는 안되지만, null은 객체를 사용해야하지만 해당 객체를 이용할 수 없을 때 항상 null이 와야한다.

boolean

데이터 타입

true

false

boolean

true

false

string

비어있지않은 문자열 전부

""(빈 문자열)

number

0이 아닌 모든 숫자, 무한대(Infinity) 포함

0, NaN

object

모든 객체

null

undefined

X(해당없음)

undefined

number

부동소수점 숫자는 소수점 아래 17자리까지 정확하지만 사칙연산에 있어서는 부정확하다.

a = 0.1
b = 0.2
a+b // 0.30000000000000004
console.log(a+b == 0.3) //=> false

0.1 + 0.2가 0.3이 아닌 0.30000000000000004를 반환하는 것을 볼 수 있다. 따라서 부동소수점 숫자를 비교할때는 이러한 버그를 인지하고 다른 방법을 써야한다.

Number.MIN_VALUE // 5e-324
Number.MAX_VALUE // 1.7976931348623157e+308
isFinite(123124124123123) // true
isFinite(Infinity)        // false

최솟값과 최대값은 MIN_VALUE, MAX_VALUE를 통해서 알 수 있으며, 해당 숫자가 유효한 범위안에 있는지는 isFinite() 함수를 사용하면된다.

NaN

NaN은 Not a Number으로 의도한 조작이 실패했을 때 반환되는 값이다. NaN은 어떠한 값도 일치하지 않으며, NaN끼리도 일치하지 않는다.

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

그러므로, isNaN() 함수를 따로 제공해준다.

원시 값과 참조 값

자바스크립트 변수는 변수가 가져야할 데이터 타입에 대한 규칙이 없으므로 변수의 값과 데이터 타입은 실행 중에 바뀔 수 있다.

원시 값은 단순한 데이터이며, 참조 값은 여러 값으로 구성되는 객체를 가리킨다. 변수에 값을 할당하면 자바스크립트 엔진은 해당 값이 원시 데이터인지 참조 데이터인지 판단한다.

원시타입은 Undefined, Null, Boolean, 숫자, 문자열이다. 참조 값은 메모리에 저장된 객체로, 자바스크립트는 메모리 공간을 직접 조작하는 것이 불가능하며, 객체를 조작할때는 사실 해당 객체에 대한 참조를 조작하는 것이다.

동적 프로퍼티

참조 값을 다룰때는 언제든 프로퍼티와 메서드를 추가하거나 바꾸고 삭제할 수 있다.

var person = new Object();
person.name = "Faker";
console.log(person.name); // "Faker"

객체를 생성한 후 프로퍼티를 추가했다. 이 시점부터 객체가 파괴되거나 프로퍼티를 명시적으로 제거하기 전까지는 해당 프로퍼티에 접근할 수 있다.

var name = "Faker";
name.age = 24;
console.log(name.age); // undefined

원시값에는 프로퍼티가 없으며, 추가하려해도 오류가 발생하지는 않지만 바로 사라진다. 동적으로 프로퍼티를 추가할 수 있는 값은 참조값 뿐이다.

값 복사

원시 값을 다른 변수로 복사할 때는 현재 저장된 값을 새로 생성한 다음 새로운 변수에 복사한다.

var num1 = 4;
var num2 = num1;

console.log(num1 , num2); // 4 4
num1 = 5;
console.log(num1 , num2); // 5 4

여기서 복사된 값 num2는 num1에 저장된 값과는 완전히 분리되어있는 것을 확인할 수 있다.

참조 값은 객체를 복사하면 그 값이 객체 자체가 아니라 힙에 저장된 객체를 가리키는 포인터이다.

var obj = Object();
var obj2 = obj;

obj.name = "Faker";
console.log(obj2.name);
obj2.name = "Clid";
console.log(obj.name);

다음과 같이 객체를 조작하면 다른 객체에도 영향이 가는 것을 확인할 수 있다.

매개변수

ECMAScript의 함수 매개변수는 모두 값으로 전달된다. 함수 외부에 있는 값은 함수 내부의 매개변수에 복사되는데, 이때 변수의 값을 복사하는 것과 같다. 변수는 값으로도, 참조로도 접근가능하지만 매개변수는 오직 값으로만 전달된다.

function addTen(num){
  // 여기서 매개변수 num은 지역변수이다.
  num += 10;
  return num;
}

var count = 20;
var result = addTen(count);
console.log(count); // 20
console.log(result); // 30
function setName(obj){
  obj.name = "Faker";
}
var person = new Object();
setName(person);
console.log(person);
[object Object] {
  name: "Faker"
}

obj는 함수에 값 형태로 전달되었지만, 참조를 통해서 객체에 접근한다. 함수 내부에서 obj에 name 프로퍼티를 추가하면 함수 외부에서도 반영되는데 obj가 가리키는 것은 힙에 존재하는 전역 객체이기 때문이다.

function setName2(obj){
  obj.name = "Faker";
  obj = new Object();
  obj.name = "Greg";
}

var person2 = new Object();
setName2(person2);
console.log(person2);
[object Object] {
  name: "Faker"
}

만약 person2가 참조로 전달되었다면, person2의 name 프로퍼티 값은 Grag로 변경되어야하지만 "Faker"그대로이다. 함수에 값을 전달했기때문에 함수 내부에서 매개변수의 값이 바뀌었음에도 불구하고 원래 객체에 대한 참조를 그대로 유지한 것이다. 함수 내부에서 새로운 객체를 생성하면, obj는 지역 객체를 가리키는 포인터가 되며, 이 지역 객체는 함수가 실행을 마치는 순간 즉시 파괴된다.

타입 판별

typeof 연산자는 변수가 원시 타입인지 파악하기에 최상이지만, 참조값에 대해서는 판별하기 어렵다. 이러한 경우에 instanceof 를 사용하면된다.

variable instanceof constructor
console.log(person instanceof Object); // true

모든 참조 값은 Object의 인스턴스인 것으로 정의되어 있으므로 항상 true를 반한환다.

연산자

일치/불일치 vs 동일/비동일 연산자

동일(==)/비동일(!=) 연산자와 일치(===)/불일치(!==) 연산자는 같은 일을하지만 일치, 불일치 연산자는 피연산자의 타입을 변환하지 않고 그대로 비교한다.

console.log("55"==55); // true
console.log("55"===55); // false

동일 연산자(==)는 문자열을 숫자로 변환한 다음 비교를 하므로 두 값이 동일하다고 본다. 하지만 일치 연산자(===)는 변환하지 않은 상태에서 비교하므로 일치하지 않다고 반환한다.

console.log(undefined == null); // true
console.log(undefined === null); // false

함수

ECMAScript 함수는 매개변수 숫자를 따지지 않으며 데이터 타입도 체크하지 않는다. 함수에서 매개변수를 두 개 받도록 만들었더라도 반드시 매개변수 두 개를 넘겨야하는 건 아니다. ECMAScript의 매개변수가 내부적으로는 배열로 표현되기 때문이다. 이 배열은 항상 함수에 전달되지만 함수는 배열에 어떤 값이 들어있는지 체크하지 않는다. 함수는 arguments라는 객체를 통해서 매개변수 값에 접근할 수 있다.

function sayHi(){
  console.log(arguments);
}
sayHi('test1','1234', '25');
[object Arguments] {
  0: "test1",
  1: "1234",
  2: "25"
}

arguments는 인덱스 값으로 접근할 수 있다.

ECMAScript 함수에는 다른 언어에서 사용하는 오버로딩이 없다.같은 이름으로 함수를 여러 번 정의하면 마지막 함수가 할당된다.

Last updated