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

Suh, Hyunwook·2021년 6월 8일
0


오늘의 학습자료 : 자바스크립트 7 - 연산자(Operator)

두 번째 글에서는 '연산자 및 함수'에 대해서 다뤄보고자 합니다. 특히, JS 연산자를 접하면서 느껴지는 두 번째 감정은 '두려움'입니다.. 문법이 난해하다는 얘기를 하고자 하는 것이 아니라, 암묵적 형변환이 이렇게 잦은데, 에러가 나지는 않을까? 하는 생각이 들곤 합니다.

C로 알고리즘 문제들을 해결할 때에는 디버깅을 달고 살았습니다. 사소한 세미콜론, 데이터 타입 정의, 함수의 순서, 메모리 크기 설정의 엄격함 때문입니다. 물론, 속도와 메모리면에서는 유리한 점이 있기는 합니다. C를 사용하면서 '강박'에 가까운 디버깅을 경험한 이후, 암묵적 형변환을 접하면서 관대함(?)까지도 느껴집니다. 🤪

1. 자바스크립트에서는 함수도 값이다.

#include <iostream>
using namespace std;
int arr[10] = { 1,2,3 };
int isExist(int num) {
	for (int i = 0; i < 10; i++) {
		if (arr[i] == num) {
			return 1;
		}
	}
	return 0;
}
int main() {
	int ret = isExist(2); // C에서도 함수 자체를 값(Value)처럼 정의할 수 있다. 
	if (ret == 1) cout << "존재";
	return 0;
}

단, javascript에서는 더욱 유연한 범위에서 객체로서 함수를 사용합니다. 예를 들어, 함수가 Object 안의 프로퍼티(속성)처럼 값(Value)으로서 객체 안에 저장될 수 있고, 이 경우 이 함수를 메서드(method)라고 부르죠. 이 부분은 C++의 Class 개념과 상당부분 유사한 것 같습니다.

  • 함수의 Parameter로 전달 가능
function cal(func, num) { 
  return func(num); //2. parameter로 넘겨받은 함수를 return
}
function increase(num) {
  return num+1;	//3. return 받은 함수를 연산 
}
function decrease(num) {
  return num-1;
}
alert(cal(increase,1)); //1. 함수를 호출
alert(cal(decrease,1));
function cal(mode) {
 var funcs = {
   'plus':function(left, right){return left+right},
   'minus':function(left, right){return left-right}
	}
 return funcs[mode]; //2. plus이면? mode는 plus가 됨 
}
alert(cal('plus')(2,1)); //1. 함수를 호출
alert(cal('minus')(2,1));
  • 함수는 배열에도 포함 가능
var process = [
  function(input){return input+10;},
  function(input){return input*input;},
  function(input){return input/2;}
];
var input = 1;
for (var i = 0; i<process.length; i++) {
  input = process[i](input); 
  // process[0](1)은 function(1)이고, return 1+10이다.
}
alert(input);

이처럼, 함수를 리턴값이나 배열에 포함시키는 것처럼 '정말로' 값처럼 사용합니다. devbox님의 코드를 참조하였으며, 자세한 내용은 이 내용을 참고하시면 되겠습니다.

2. 자바스크립트의 독특한 연산자 : Type 연산자

앞서 말했듯이, JS에서는 변수를 정의할 때, type이 동적으로 정해지기 때문에 type을 비교할 필요성이 있고, 이를 연산할 필요도 있는 것 같습니다.

C언어에서도 비교 연산자인 '==','!='은 있으나 JS에는 '==='과 '!=='라는 개념도 있습니다. 후자의 경우, type을 비교하는 연산자입니다.

POIEMA의 예시를 보았을 때, JS언어가 '알쏭달쏭'하다고 느껴졌습니다. 아래 예시는 정말 주의가 필요할 듯 합니다. cada님의 설명을 추가로 보시면 더욱 좋습니다.

그 중 소개드리고 싶은 예제는 다음 예제입니다.

if([] == 0) {
  console.log('어, 이게 왜 되지?');
}

// 1단계 - [] == 0 => '' == 0  :  배열 []이 빈 문자열 ''로 변환된다.
if('' == 0) {
  console.log('어, 이게 왜 되지?');
}

// 2단계 - '' == 0 => 0 == 0 : 문자열 ''이 숫자 0으로 변환된다.
if(0 == 0) {
  console.log('어, 이게 왜 되지?');
}

// 3단계 - 0 == 0 => true
if(true) {
  console.log('어, 이게 왜 되지?');
}

그에 앞서, javascript에는 원시값(primitive value)참조값(reference value)가 있습니다. 먼저, 원시값이란 단순한 데이터를 말하며, number, string, boolean, null, undefined 등의 형태를 말합니다. 참조값은 원시값을 참조하는, 일반적으로는 객체를 일컬으며 array, function 등의 형식을 취합니다.

참조값과 원시값은 비교할 수 없으므로, 묵시적 형변환에 따라 참조값이 원시값으로 변환되기 됩니다. 이 부분을 알고 있어야, 헷갈리는 부분을 이해할 수 있습니다.

먼저, 위 예제에서 참조값인 []는 == 연산에 사용될 경우에는 toString() 연산을 통해 원시값으로 형변환이됩니다. ''는 false값이고, 숫자형으로 묵시적 변환이 되면, 0이 됩니다. 그렇기에 []과 0이 같다는 결과가 나오는 것입니다.

<참고>
자바스크립트에서 false로 정의되는 것들은 다음과 같습니다.
"", 0 , undefined, NaN, null
즉, Javascript에서는 비교 시 묵시적 형변환(예를 들면, 숫자 문자 연산 시, 숫자에 toString 메서드가 작동되는 것)이 일어나기 때문에, 이를 염두한 연산을 해야한다는 것입니다.

0개의 댓글