개발 기술/사소하지만 놓치기 쉬운 개발 지식

in, hasOwn, hasOwnProperty의 차이

by GicoMomg (Lux) 2022. 4. 2.

💡 JS에서는 객체에 특정 속성이 있는지 체크할 수 있는 방법이 in, hasOwn, hasOwnProperty가 있다. 그런데, 이 메소드는 어떤 차이가 있길래 여러 개가 존재하는걸까? 이번시간에는 이 세 메소드의 차이에 대해 알아보았다.(차이점만 보고 싶다면, 바로 2.메소드 간 차이보기로 넘어가자)


1. 각 메소드 알아보기

1) in 연산자

  • in연산자는 특정 속성이 해당 객체에 있는지 여부를 boolean으로 리턴해준다.
속성 in 객체

(1) array의 경우

  • array에서 in연산자를 사용하면, 인덱스에 대해서만 체크할 수 있다.
const arr = ['apple', 'orange', 'banana'];

console.log(0 in arr);       // true
console.log((1+1) in arr);   // true
console.log('apple' in arr); // false

(2) string의 경우

  • string에서는 in연산자를 사용하면 에러가 발생한다.
  • 하지만, new String로 선언하면 string에서 사용할 수 있는 속성(length)에 대해서 체크할 수 있다.
const text = new String('hello');
console.log('length' in text);  // true


(3) object의 경우

  • object에서 in연산자를 사용하면, 해당 객체에 특정 속성이 있는지 체크할 수 있다.
const obj = {'a': 1, 'b': 2, 'c': 3};
console.log('a' in obj);  // true
console.log(1 in obj);    // false

(4) 상속된 속성

  • JS에서는 객체를 생성하면 우리는 JS에서 제공하는 내장 메소드에 접근할 수 있다.
  • 이는 JS의 프로토타입 체인 때문인데, 특이한 점은 이 체인으로 인해 객체의 내장 속성을 체크할 수 있다!
console.log('slice' in []); // true



2) hasOwnProperty

  • hasOwnProperty()은 해당 객체에 특정 속성이 있는지 여부를 boolean으로 리턴해준다.
obj.hasOwnProperty(property)

(1) array의 경우

const arr = ['apple', 'orange', 'banana'];

console.log(arr.hasOwnProperty(1));       // true
console.log(arr.hasOwnProperty('apple')); // false

(2) string의 경우

  • new 생성자를 이용해 String을 선언하면, length 속성이 있는지 체크할 수 있다.
const text = new String('hello');
console.log(text.hasOwnProperty('length'));  // true

(3) object의 경우

const obj = {'a': 1, 'b': 2, 'c': 3};

console.log(obj.hasOwnProperty('a'));  // true
console.log(obj.hasOwnProperty(1));    // false

(4) 상속된 속성

  • hasOwnProperty()는 프로토타입 체인으로 인해 객체에서 기본 제공되는 속성에는 접근할 수 없다.
console.log([].hasOwnProperty('slice')); // false



3) Object.hasOwn()

  • 기능은 hasOwnProperty()와 유사하다.
Object.hasOwn(target, property);

(1) array의 경우

const arr = ['apple', 'orange', 'banana'];

console.log(Object.hasOwn(arr, 1));       // true
console.log(Object.hasOwn(arr, 'apple')); // false

(2) string의 경우

  • new 생성자를 이용해 String을 선언하면, length 속성이 있는지 체크할 수 있다.
const text = new String('hello');
console.log(Object.hasOwn(text, 'length'));  // true

(3) object의 경우

const obj = {'a': 1, 'b': 2, 'c': 3};

console.log(Object.hasOwn(obj, 'a'));  // true
console.log(Object.hasOwn(obj, 1));    // false

(4) 상속된 속성

  • 프로토타입 체인으로 인해 객체에서 기본 제공되는 속성에는 접근할 수 없다.
console.log(Object.hasOwn([], 'slice')); // false






2. 메소드 간 차이점 한 눈에 보기

1) 상속된 속성

  • 프로토타입 체인으로 인해, 객체를 프로토타입 방식으로 선언하면 내장 함수를 사용할 수 있다.
  • 그런데 객체의 속성을 체크할 때 이 내장 속성도 체크할 수 있는데, in연산자만 가능하다.
const cat = {
  name: 'lala',
  age: 12,
};

// 선언된 속성
console.log('name' in cat);              // true
console.log(Object.hasOwn(cat, 'name')); // true
console.log(cat.hasOwnProperty('name')); // true

// 상속된 속성
console.log('toString' in cat); // true
console.log(Object.hasOwn(cat, 'toString')); // false
console.log(cat.hasOwnProperty('toString')); // false



2) 객체 선언 방식

  • 객체를 생성할 때 prototype 방식이 아닌 Object.create()을 사용할 수도 있다.
  • 대신 이렇게 생성된 객체에서는 prototype 메소드인 hasOwnProperty()는 사용할 수 없다.
let cat = Object.create(null);
cat.name = 'lala';

console.log('name' in cat);              // true
console.log(Object.hasOwn(cat, 'name')); // true
console.log(cat.hasOwnProperty('name')); // error



3) 오버라이드

  • 만약 객체에서 Object.hasOwn, hasOwnProperty를 오버라이드하면 기존 기능은 작동되지 않는다.
const cat = {
  hasOwnProperty: () => false,
  name: '1',
};

Object.hasOwn = () => false;
console.log('name' in cat);              // true
console.log(Object.hasOwn(cat, 'name')); // false
console.log(cat.hasOwnProperty('name')); // false



4) 클래스

  • private(#)으로 선언된 속성에는 접근할 수 없다.
class Test {
  #name = 1;
}

const test = new Test();

console.log('#name' in test);              // false
console.log(Object.hasOwn(test, '#name')); // false
console.log(test.hasOwnProperty('#name')); // false

반응형

댓글