일반적으로, 어떠한 객체에 특정한 프로퍼티가 존재하는지 검사하기 위해서는, hasOwnProperty()라는 메소드를 사용하곤 한다.

문제

그런데 재미있는 것은, 객체 자체를 key로 사용할 수 있는 연관 배열인 Dictionary의 경우, String이 아닌 객체를 값으로 사용 시 hasOwnProperty()가 우리가 의도한 대로 동작하지 않는다.

예를 들어,


public function test():void {
	var dict:Dictionary = new Dictionary();
	var obj:Object = {};
	
	dict[obj] = "test";
	
	trace(dict.hasOwnProperty(obj));
}

이 코드를 실행시키면, dict.hasOwnProperty(obj)부분에서 false를 리턴한다.

해결

불과 얼마 전까지만 해도 나는 이 문제를 dict[obj] != undefined와 같은 코드로 해결해왔다. 물론, 이 해결 방법이 틀렸다고는 할 수 없다.

하지만 현재는, 아래와 같이 in 연산자를 사용하는 것을 선호한다.


public function test():void {
	var dict:Dictionary = new Dictionary();
	var obj:Object = {};
	
	dict[obj] = 'test'
	
	trace(obj in dict);
}

또한 이 값을 해제하기 위해서는 아래와 같이 한다.


	delete dict[obj];

물론 undefined 또는 null을 이용하는 경우, dict[obj] = undefined와 같이 직접 그 값을 지정해주어도 큰 문제는 없으나, in 연산자를 사용하는 경우, delete를 이용하여 reference를 지워주어야 정상적으로 동작한다.

출제자의 의도 파악

왜 Dictionary에서는 hasOwnProperty()가 정상적으로 동작하지 않고, 또한 in 연산자를 사용해야만 할까?

개인적인 추측이지만, 이는 ECMAScript 표준[각주:1]과 관련이 있다고 생각한다. ECMAScript 표준에서 hasOwnProperty()는, 전달 받은 파라미터의 toString() 값을 사용하도록 정의되어 있다. 반면, Dictionary는 === 연산자, 즉 Strict Equality를 사용하는 특수한 클래스로서, 현재처럼 hasOwnProperty()로는 Property 체크를 하지 못하는 것이 정상. 만약 이를 바꾸게 되면 표준에서 벗어나게 된다.

추가 팁

한편으로 undefined 또는 null을 사용하는 경우, in 연산자를 대신할 수 있지만, 그 의미는 각각 다르다. in을 사용하는 경우, '해당 키 자체가 존재하는지' 여부를 확인하는 방법이며, undefined는 '해당 키의 값이 지정되었는지' 여부를 확인하는 방법, 그리고 null은 '해당 키의 값이 의미 있는 형태로 존재하는지' 여부를 확인하는 방법에 각각 해당한다.

일반적인 경우에는 in 연산자, undefined, null 중 어떤 것을 사용해도 딱히 문제가 발생하진 않을 것이다. 그렇다고는 해도, '해당 키가 연관 배열 내 존재하는지 여부'에 대해 확인하기 위해 이와 같은 코드를 작성하는 것이 가장 일반적이므로, in 연산자 및 delete 연산자를 사용하는 것을 권장하는 바이다.

결론

hasOwnProperty()는 분명 친숙한(?) 메소드이지만, Dictionary에서는 의도대로 잘 동작하지 않는다. 그에 대한 해결책으로 in 연산자를 사용하거나, 또는 undefined, null 값과 비교하는 방법 등이 존재한다. 각각의 방법마다 서로 다른 의미를 가지며, 일반적인 경우에는 in 연산자를 이용한 방법을 사용하는 것을 추천한다.

Reference

See Also

Associate

  1. http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf [본문으로]
  2. 본인이 처음 이 문제를 접한 당시에는, Dictionary의 hasOwnProperty()의 로직에 문제가 있다고 생각하고 있었으나, 김학영님과의 메신저(GoogleTalk) 상 토론을 통해 이 문제에 더욱 깊게 다가설 수 있는 계기가 되었다. [본문으로]
저작자 표시 비영리 변경 금지
Posted by 찬익

트랙백 주소 : http://blog.chanik.com/trackback/47 관련글 쓰기

댓글을 달아 주세요

  1. BlogIcon hika 2010/01/01 16:23  댓글주소  수정/삭제  댓글쓰기

    in 연산자가 컴마다음에 포스팅할까 했던 거였는데 ㅎㅎ

    • BlogIcon 찬익 2010/01/01 21:59  댓글주소  수정/삭제

      앗 그렇군요 ㅎㅎ
      컴마처럼 심도 깊은 내용 기대해도 될까요?
      포스팅되면 트랙백 걸도록 하겠습니다. ㅎㅎ

    • BlogIcon hika 2010/01/02 11:29  댓글주소  수정/삭제

      이미 충분히 여기서 적어주셔서 별로 필요가 없을듯 ^^
      그외에도 연산자는 수없이 많으니 다른거나..ㅎㅎ

    • BlogIcon 찬익 2010/01/04 03:33  댓글주소  수정/삭제

      그렇군요 ㅎㅎ
      언제라도 보완할 내용이 생각나시면, 포스팅 하신 후 알려주세요 ㅎㅎ

  2. BlogIcon 지돌스타 2010/01/04 19:51  댓글주소  수정/삭제  댓글쓰기

    정말 미세한 차이같지만 분명한 차이가 있네요. 차이=찬익? 뭔 차이? 퇴근시간 넘었군요. ㅡㅡ