...
프로그래밍 언어에서의 in 연산자
파이썬 프로그래밍을 하다가 자바스크립트 프로그래밍을 하다 보면 은근히 햇깔리는 부분이 바로 in 연산자 사용처이다.
예를들어 파이썬의 in 연산자는 멤버십 연산자로서, 문자열이나 리스트나 튜플과 같이 연속적인 자료구조에 속한 멤버를 확인하기 위한 연산자이다. 그래서 아래와 같이 리스트를 순회할 일이 있다면 for in문을 통해 가능하다.
fruits = ["apple", "banana", "orange"]
for fruit in fruits:
print(fruit)
그런데 똑같이 자바스크립트로 배열에 in 연산자를 사용하면 다음과 같이 출력된다.
const fruits = ["apple", "banana", "orange"];
for (fruit in fruits) {
console.log(fruit);
}
이러한 현상이 일어나는 이유는 자바스크립트 프로그래밍 언어에서의 in 연산자는 기본적으로 객체 용이기 때문이다. 자바스크립트의 배열도 결국 해시테이블로 이루어진 객체와 다름이 없다.
따라서 배열에다 in 연산자를 쓰면 key 값인 인덱스를 검사하게 되는 꼴이 되어 버려 위와 같이 출력되어 버리는 것이다.
만일 배열을 파이썬 처럼 순회하고 싶다면 for in 문이 아닌 for of 문으로 순회하여야 한다.
자바스크립트 in 연산자
이처럼 자바스크립트의 in 연산자는 객체의 속성을 확인하기 위한 연산자로서, 객체가 가지고 있는 프로퍼티 및 메소드의 존재 여부를 Boolean으로 반환한다. 예를 들어 person이라는 객체에 name이라는 속성과 sayHello라는 메서드가 있는지 확인하려면 다음과 같이 할 수 있다.
var person = {
name: "Alice", // name 속성
sayHello: function() { // sayHello 메서드
console.log("Alice가 인사합니다.");
}
};
console.log("name" in person); // true
console.log("sayHello" in person); // true
console.log("age" in person); // false
in 연산자는 상속된 속성이나 메서드도 검사한다. 사용자 정의 객체인 person은 내부적으로 Object라는 생성자 함수로부터 상속받기 때문에 toString() 메서드를 정의하지 않아도 사용할 수가 있다. 이 상속된 속성에 대해 in 연산자로 검사가 가능한 것이다.
console.log("toString" in person); // true
in 연산자 쓰임새
in 연산자의 쓰임은 다양하게 활용될 수 있겠지만, 주로 특정 메소드, 프로퍼티 key값 이름의 존재 여부를 검증하기 위한 목적으로 많이 사용된다. 즉, 해당 객체에 존재하지도 않는 메소드나 프로퍼티를 동작시킬 경우 에러가 발생할 수 있으므로 사전에 여부를 먼저 확인하기 위한 목적이 크다.
// person 객체에는 name과 sayHello가 있지만 age와 sayBye가 없다.
let person = {
name: "Alice",
sayHello: function() {
console.log("Alice가 인사합니다.");
}
};
// in 연산자를 사용하여 person 객체에 age와 sayBye가 있는지 확인
console.log("age" in person); // false
console.log("sayBye" in person); // false
// person 객체에 없는 age와 sayBye를 사용하려고 하면 에러가 발생
console.log(person.age); // undefined
person.sayBye(); // TypeError: person.sayBye is not a function
// in 연산자를 사용하여 person 객체에 age와 sayBye가 있는 경우에만 사용하도록 조건문을 작성
if ("age" in person) {
console.log(person.age); // 이 코드는 실행되지 않는다.
}
if ("sayBye" in person) {
person.sayBye(); // 이 코드도 실행되지 않는다.
}
또는 객체에 특정 속성이나 메서드가 없는 경우에만 새로 추가하고 싶다면 다음과 같이 할 수 있다.
if (!("age" in person)) {
person.age = 25; // age 속성을 추가합니다.
}
in 연산자 주의점
1. 존재 자체만 확인한다
첫째, in 연산자는 속성이나 메서드의 존재만 검사하고, 값은 검사하지 않는다. 예를 들어, person이라는 객체에 age라는 속성이 있지만 값이 undefined인 경우에도 다음과 같이 결과가 나오게 된다.
let person = {
name: "Alice",
age: undefined
};
console.log("age" in person); // true
in 연산자가 객체의 속성의 존재 여부만을 판단하고 속성의 값은 무시하기 때문에, 따라서 이 경우에는 값도 추가적으로 필히 확인해주어야 한다.
console.log("age" in person && person.age !== undefined); // false
2. for in 과 in 연산자는 다르다
둘째, in 연산자는 for…in 반복문과 혼동하지 않아야 한다. 분명 포스팅 초반에선 for in 문으로 예시를 들었지만 이는 조금 친근하게 in 연산자에 대해서 접근하기 용이하게 표현을 한 것이지, 이 둘은 엄밀히 따지면 서로 전혀 다른 존재이다.
그런데 하나는 반복문 문법이고 하나는 객체를 검사하는데 이용되기 때문에 둘을 혼동해도 자바스크립트 코딩하는데 문제가 되지는 않는다.
let person = {
name: "Alice",
sayHello: function() {
console.log("Alice가 인사합니다.");
}
};
// in 연산자 사용 예시
console.log("name" in person); // true
console.log("sayHello" in person); // true
console.log("age" in person); // false
// for...in 문 사용 예시
for (var prop in person) {
console.log(prop + ": " + person[prop]);
}
// name: Alice
// sayHello: function() { console.log("Alice가 인사합니다."); }
in 연산자와 hasOwnProperty() 메서드
자바스크립트에서 객체의 특정 프로퍼티 속성을 검사하는 기능으로서 in 연산자와 같이 hasOwnProperty() 메서드가 존재한다.
let person = {
name: "Alice",
sayHello: function() {
console.log("Alice가 인사합니다.");
}
};
if ("sayHello" in person) {
person.sayHello(); // Alice가 인사합니다.
}
if (person.hasOwnProperty("sayHello")) {
person.sayHello(); // Alice가 인사합니다.
}
다만 in 연산자와의 차이점은 hasOwnProperty() 는 실제 객체가 가진 프로퍼티나 메소드 값만 확인하여 불리언 값을 반환한다는 특징이 있다.
예를들어 in 연산자는 상속된 속성이나 메서드도 검사하고, hasOwnProperty() 메서드는 상속된 속성이나 메서드를 검사하지 않는다. 그래서 아래와 같이 서로 다른 결과가 나타나게 된다.
'toString' in person // 상속된 프로토타입 메서드를 취급한다.
// true를 반환
person.hasOwnProperty('toString') // 상속된 프로토타입 메서드를 취급 안한다.
// false를 반환
person 사용자 정의 객체는 toString() 메서드를 호출하여 사용할 수 있지만, 엄밀히 말하자면 상속하고 있는 Object 부모 객체의 기능을 빌려와 사용할 뿐이지, person 객체가 소유한 객체는 아니기 때문이다.
즉, in 연산자는 객체의 멤버십을 검사하는 연산자이고, hasOwnProperty() 메서드는 객체의 자체 속성 여부를 검사하는 메서드라고 보면 된다.
# 참고자료
https://webisfree.com/2021-03-21/[%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8]-in-%EC%97%B0%EC%82%B0%EC%9E%90-%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95%EA%B3%BC-%EC%9D%91%EC%9A%A9
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Operators/in
이 글이 좋으셨다면 구독 & 좋아요
여러분의 구독과 좋아요는
저자에게 큰 힘이 됩니다.