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

Suh, Hyunwook·2021년 6월 7일
0


오늘의 학습자료 : 자바스크립트 5 - 자바스크립트의 기본 문법

C언어를 중심으로 알고리즘 풀이를 한 이후 처음 Javascript를 접하면서, '신기'하다는 느낌을 많이 받습니다. 어떤 사물이나 현상을 처음 보았을 때, 신기하다는 느낌이 들기 위해서는 분명 같은 범주에 있는 유사한 것을 경험한 이후, 같은 범주에 속하면서도 다른 것을 경험했을 때, 둘의 차이를 느끼면서 신기하다고 느끼게 됩니다.

C언어와 유사하여 반가운 문법도 있지만, 분명 Javascript의 개성이 느껴지는 지점에서는 마찬가지로 '신기'하다는 느낌이 있는 것입니다.

Javascript를 학습함에 있어, '신기함'을 느끼면서 공부를 하게 되면 더욱 와닿게 공부할 수 있다는 취지에서 이 글을 작성하게 되었습니다. 아직은 고-오급 용어에 익숙하지 않으므로, 코린이의 입장에서 다소 투박한 비교를 해보고자 합니다. 역시나 고수분들의 많은 지적을 기대하겠습니다.

(이 글은 바닐라코딩 사전학습 가이드에서 추천한 Poiemaweb의 JS문법 내용을 학습하며 작성하겠습니다.👀)

1. Javascript의 변수는 할당 값에 의해서 동적으로 결정됨

JS의 변수는 C언어와 달리 변수 선언 시 데이터 타입을 미리 설정하지 않고, 변수에 할당된 값에 의해서 동적으로 변수의 타입이 결정되는 점이 있습니다. C의 경우에는 int, char, string, double의 형식으로 데이터 타입과 변수에 할당 가능한 메모리의 크기를 설정하는 반면, JS에서는 할당된 값의 타입에 의해서 변수의 타입이 결정됩니다.

따라서, C에서는 별도로 타입연산자를 사용할 필요가 크게 없습니다.

var type = typeof 'Hi!' // string 
string str = 'Hi!'

타입이 애초에 떡하니 써있는데, 굳이... 또한 C에서는 변수의 타입을 정적으로 고정시켜 버리기 때문에, casting을 하는 경우가 종종 있습니다.

char ch = 'a'
int num = (int)('a');

Javascript에서는 타입이 동적으로 결정되는 것과 같이, 할당된 값에 따라 메모리가 할당됩니다. 이런 특징 속에서 JS에서는 묵시적 형변환이라는 것이 더욱 유연하게 적용되는 것이 아닌가 합니다.

var foo = 1 + '10'; // '110'
var bar = 1 * '10'; // 10

JS에서는 이러한 연산을 암묵적으로 타입을 강제 변환시켜 연산하게 해준다는 것이 '신기'하다고 느껴지는 것입니다.

2. Javascript 객체는 C의 구조체와 유사하다

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'
console.log(person.sayHello()) // Hi! My name is Lee

물론 C++의 class가 더 유사하다고 볼 수는 있겠지만, 필자는 class의 개념보다는 구조체에 더 익숙하기 때문에 구조체로 한번 비교해보도록 하겠습니다. 위의 코드는 JS기준 코드입니다

#include <iostream>
#include <string>
using namespace std;
struct person {
	string name = "Lee";
	string gender = "male";
};
void sayHello(person name) {

	cout << "Hi! My name is" << " " << name.name;
	
}

int main() {

	person Suh;
	cout << Suh.name << '\n';
	cout << Suh.gender << '\n';
	sayHello(Suh);

	return 0;
}

이처럼, C의 구조체 개념은 JS의 객체 개념과 상당 부분 유사합니다.
C의 절차지향형 성격에서의 구조체가 발전되면서 객체지향언어인 C++, JS에서 object와 class의 개념이 구축된 것으로 보입니다.
(출처: 해당 링크를 타고 들어가시면 더욱 더 심도 있는 C++과 JS의 비교를 보실 수 있습니다. https://doitnow-man.tistory.com/129)

3. 유효범위의 차이 : Block-level scope와 Function-level scope

C언어에서는 일반적으로 변수 선언이 Block-level scope에 맞춰져 있으며, 쉽게 말해 중괄호인 '{}'에 쌓여있는 코드의 덩어리를 의미합니다. 예를 들면, if의 블록, for의 블록 function의 블록 등이 있고, 이 모두를 통칭하는 것이죠.

#include <iostream>
using namespace std;
//1. 모두를 아우르는 전역변수
int num = 1;
void run() {

	int num = 8;

}
int main() {
	//2. For문의 세계에서의 num
	for (int i = 0; i < 10; i++) {
		int num = 3;
	}
	//3. run함수의 세계에서의 num
	run();

	return 0;
}

C언어의 경우 각 세계의 변수가 엄격하게 나눠져 있으며, 이렇게 블록 단위로, 즉 각 세계별로 변수가 달라집니다. num이라는 변수는 각 세계에서는 각기 다른 얼굴을 하고 있는 것입니다.

단, JS의 Function-level scope에서는 함수 내에서는 var로 정의한 변수가 실행되면 for문 밖에서도 동작이 됩니다. 즉, 함수 내에서는 for문 밖에서도 별도의 추가선언 없이 그 변수를 사용할 수 있는 것이죠.

function main() {
	for (int i = 0; i<3; i++) {
      var temp = 'hi';
      /*do something*/
    }
  console.log(temp);
}

위의 소스코드는 '오지고지리고알파고포켓몬고'님의 설명링크를 참조하였음을 밝힙니다.
오지고지리고알파고포켓몬고님의 추가 설명을 보시면 이해가 더욱 되실 것입니다. (닉네임처럼 오지는 설명이셨습니다. 감사합니다. 🙏)

여기서 가장 놀라운 점 중 하나는 전역변수까지도 덮어버린다는 점입니다.

function main() {
	var name = "yudoomack";
	var names = ['kim', 'lee', 'park'];

	for (var i = 0; i<names.length; i++) {
		var name = names[i];
  		if (name === 'kim') {/*do something*/}
	}
  	console.log(name);
}

C의 heavy user분들께서는 익숙치 않으시겠지만 name에는 yudoomack을 덮고, kim이 출력된다고 합니다.

'오지고'님의 블로그를 보시면, 이런 경우 협업 시 또는 외부 js library를 불러와서 사용할 시 전역변수가 영향을 받을 수 있어 치명적일 수 있다고 하네요. 🌲Javascript 꿈나무🌲 로서, 이러한 현상에 대한 추가적인 내용은 'Hoisting'과 'Closure'를 추가적으로 학습하며, 방지법을 알아가보도록 하겠습니다.

0개의 댓글