[Javascript] C와 비교하며 학습하는 Javascript (3)

Suh, Hyunwook·2021년 6월 12일
0
post-thumbnail

오늘의 학습자료 : 자바스크립트 10 - 객체(Object)

1. Javascript는 객체(Object) 기반의 스크립트 언어이다.

C에서는 기본적으로 Data Type (예를 들면, char, int, double) 및 struct를 사용한 구조체를 통해 메모리 공간을 할당하여, main() 함수 등 function 을 통해 compile을 하는 방식으로 구동합니다. C에서는 Object라는 개념 자체를 주로 사용하지는 않으나, Value가 포함된 메모리 공간을 객체로 지칭하기는 합니다. 소스코드 영역이 아닌 컴파일 이후 메모리의 관점에서 객체의 개념을 사용하기 때문에, 자주 쓰지는 않는 것입니다.

Javascript의 경우, Data type 자체를 유저가 정하지는 못하나(=즉, 메모리를 사용자가 임의로 제어하는데 제한적이지만...), 객체라는 개념을 소스코드 수면 위로 드러내어 이 객체를 유연하게 사용할 수 있도록 합니다.

Javascript의 자료형은 앞에서도 학습하였지만 다시 한번 정리하면,

  • 원시타입(Primitive type)
    📣 string, number (NaN 포함), Boolean, Undefined
  • 객체(Object)타입
    📣 원시 타입을 제외한 모든 연산 가능한 데이터 (함수, 배열, 정규표현식 등)
    📣 키(key)와 값(value)로 이뤄진 속성(Property)의 집합
    📣 프로퍼티 값으로 함수가 사용될 시 '메소드(Method)'라고 부름

물론, 원시타입 자료형도 object는 아니지만, object 내에서는 멤버 속성(Property)로 사용될 수 있습니다. 아래 코드는 객체 리터럴 방식을 사용한 객체 정의 방법입니다.

//1) 빈 객체를 선언하는 방법 
var emptyObject = {};
console.log(typeof emptyObject); // object

//2-1) Key와 Value를 사용하여 객체 정의하기 
//2-2) 객체 내에는 sayHello라는 function, 즉 메서드가 들어있음 
var person = {
  name: 'Lee',
  gender: 'male',
  sayHello: function () {
    console.log('Hi! My name is ' + this.name);
  }
};

console.log(typeof person); // object
console.log(person); // {name: "Lee", gender: "male", sayHello: ƒ}

person.sayHello(); // Hi! My name is Lee

위에서 언급하였듯이, javascript는 객체를 다룸에 있어 더욱 유연합니다. 예를 들어, console.log(person) 부분에서 C의 경우, 객체라는 개념을 소스코드 영역에서는 따로 다루지 않기 때문에, 각 Property를 하나씩 출력해야하나, javascript에서는 객체 단위로 출력이 가능합니다.

두 번째로, 배열을 출력함에 있어서도, javascript에서는 console.log(array) 와 같은 형식으로 출력 가능하나, C에서는 배열 내 value를 for문 등으로 하나씩 출력하는 점도 같은 맥락이지요.

다음 사항으로는, 위에서 본 객체리터럴 방식의 객체 정의 외에, 생성자 함수방식입니다. 이 부분이 C의 구조체나, C++의 클래스 개념과 많이 닮았습니다. 여러 객체를 생성할 시 일반식을 정의한 뒤에, Instance를 사용하여, 객체 생성 과정을 간소화 하는 방법입니다.

// 생성자 함수 -> 객체의 템플릿입니다.
function Person(name, gender) {
  var married = true; // PRIVATE 
  this.name = name; // PUBLIC 
  this.gender = gender; // PUBLIC
  this.sayHello = function(){ // PUBLIC
    console.log('Hi! My name is ' + this.name);
  };
}

// 인스턴스의 생성
var person1 = new Person('Lee', 'male');
var person2 = new Person('Kim', 'female');

console.log(typeof person); // object
console.log(person); // Person { name: 'Lee', gender: 'male', sayHello: [Function] }

console.log(person.gender);  // 'male'
console.log(person.married); // undefined (이유: private!)

이 부분에서 this.name 부분에 있는 this는 생성자 함수가 받은 인스턴스(instance)를 가리킵니다.

this.sayHello = function(){
    console.log('Hi! My name is ' + this.name);
  };

재미있는 특성은, this에 연결되는 프로퍼티와 메소드는 public한데, 이는 즉 외부에 있는 인스턴스를 참조할 수 있다는 것입니다. 반대로, 생성자 함수 내에 선언된 일반 변수에 대해서는 private한데 이는 즉 외부에서 접근할 수는 없다는 뜻입니다.

private 하지 않은 경우, 외부 사용자가 변수를 조종할 수 있기 때문에 그를 방지하기 위함이며, public의 경우에는 외부 변수를 통해 인스턴스를 받아 생성자를 만들기 위함입니다. (자세한 내용은 생성자 호출 패턴 내용에서 다뤄보겠습니다..🙏)

2. Pass-by-reference


객체는 프로퍼티를 변경, 추가, 삭제 가능하므로, 메모리 공간 확보가 고정적이지가 않습니다. 즉, Run-time 시에 크기가 결정되며, 이 경우에는 메모리의 Heap 영역에 저장되게 됩니다.

원시변수(primitive type)의 경우, 콜스택(Call-Stack)에서 값을 바로 출력하는데 비해, 객체의 경우 메모리 힙에 저장되므로, 호출 시 메모리 힙에 저장된 객체의 주소를 호출하게 됩니다. 이 부분은 C에서 자주 사용되는 포인터(Pointer)와 Linked List의 개념과 매우 유사한 것 같네요. (❗ 위 내용은 카레유님의 메모리 구조 설명을 참고로 하였음을 밝힙니다!)

이러한 배경지식을 전제로 할 때, 아래 코드를 참고해주시면 될 것 같습니다.

// Pass-by-reference
var foo = {
  val: 10
}

var bar = foo;
console.log(foo.val, bar.val); // 10 10
console.log(foo === bar);      // true

bar.val = 20;
console.log(foo.val, bar.val); // 20 20
console.log(foo === bar);      // true

foo의 경우 리터럴 방식으로 호출된 객체이고, 따라서 힙에 저장이 됩니다. 이 경우, 콜스택에는 value가 아닌, 힙에 저장된 주소를 호출하게 됩니다. 위 코드에서 bar의 경우 foo의 객체 주소값으로 정의되어 있고, 같은 주소를 저장하고 있으므로 이 경우에는 동일한 객체를 참조하고 있습니다.

var foo = { val: 10 };
var bar = { val: 10 };

console.log(foo.val, bar.val); // 10 10
console.log(foo === bar);      // false

var baz = bar;

console.log(baz.val, bar.val); // 10 10
console.log(baz === bar);      // true

하지만, 두 번째 예시에서 foobar의 내용 자체가 같을지라도, 리터럴 방식으로 객체가 생성될 때, 다른 주소가 생성되며, 즉 다른 주소를 참조하게 됩니다. 이 경우 값은 같을 지라도 동일한 개체라고는 할 수가 없습니다.

객체라는 부분은 javascript의 유동적이고, 변화를 좋아하는 특성을 재대로 보여주는 것 같습니다. 메모리 측면에서는 동적인 관리가 이뤄지고, 사용자가 편집 및 출력을 함에 있어 관대합니다. 빠르게 변하고, 수정이 이뤄져야하며, 다른 사용자의 피드백을 즉시 반영해야하는 웹에서 적합하다는 특성이, 객체에서도 고스란히 드러나고 있는 것 같습니다. 😐

0개의 댓글