πŸ“‹ λͺ¨λ˜ μžλ°”μŠ€ν¬λ¦½νŠΈ Deep Dive | 18μž₯ ν•¨μˆ˜μ™€ 일급 객체

waterglassesΒ·2022λ…„ 4μ›” 24일
0
post-thumbnail

λͺ¨λ˜ μžλ°”μŠ€ν¬λ¦½νŠΈ Deep Dive λ„μ„œμ˜ 18μž₯을 μ •λ¦¬ν•˜μ˜€μŠ΅λ‹ˆλ‹€.

18.1 일급 객체

일급 객체
1. 무λͺ…μ˜ λ¦¬ν„°λŸ΄λ‘œ 생성할 수 μžˆλ‹€. 즉, λŸ°νƒ€μž„μ— 생성 κ°€λŠ₯ν•˜λ‹€.
2. λ³€μˆ˜λ‚˜ μžλ£Œκ΅¬μ‘°μ— μ €μž₯ν•  수 μžˆλ‹€.
3. ν•¨μˆ˜μ˜ λ§€κ°œλ³€μˆ˜μ— 전달할 수 μžˆλ‹€.
4. ν•¨μˆ˜μ˜ λ°˜ν™˜κ°’μœΌλ‘œ μ‚¬μš©ν•  수 μžˆλ‹€.

ν•¨μˆ˜λŠ” μœ„μ˜ 일급 객체의 쑰건을 λͺ¨λ‘ λ§Œμ‘±ν•œλ‹€. λ”°λΌμ„œ ν•¨μˆ˜λ„ 일급 객체이닀. 이것은 ν•¨μˆ˜λ₯Ό 객체와 λ™μΌν•˜κ²Œ μ‚¬μš©ν•  수 μžˆλ‹€λŠ” μ˜λ―Έμ΄λ‹€.

일반 객체와 같이 ν•¨μˆ˜μ˜ λ§€κ°œλ³€μˆ˜μ— 전달할 수 있으며, ν•¨μˆ˜μ˜ λ°˜ν™˜κ°’μœΌλ‘œ μ‚¬μš©ν•  μˆ˜λ„ μžˆλ‹€λŠ” 것이닀. μ΄λŠ” ν•¨μˆ˜ν˜• ν”„λ‘œκ·Έλž˜λ°μ„ κ°€λŠ₯μΌ€ ν•˜λŠ” μžλ°”μŠ€ν¬λ¦½νŠΈμ˜ μž₯점 쀑 ν•˜λ‚˜μ΄λ‹€.

18.2 ν•¨μˆ˜ 객체의 ν”„λ‘œνΌν‹°

function square(number){
	return number * number;
}

console.log(Object.getOwnPropertyDescriptors(square)); //{length :~~, name: ~~, arguments: ~~, caller:~~, prototype:~~}

//__proto__λŠ” square ν•¨μˆ˜μ˜ ν”„λ‘œνΌν‹°κ°€ μ•„λ‹ˆλ‹€.
console.log(Object.getOwnPropertyDescriptor(square, '__proto__')); //undefined

// __proto__λŠ” Object.property 객체의 μ ‘κ·Όμž ν”„λ‘œνΌν‹°λ‹€.
cosole.log(Object.getOwnPropertyDesciptor(Object.prototype, '__proto__'));

arguments, caller, length, name, prototype ν”„λ‘œνΌν‹°λŠ” λͺ¨λ‘ ν•¨μˆ˜ 객체의 ν”„λ‘œνΌν‹°μ΄λ‹€. __proto__λŠ” μ ‘κ·Όμž ν”„λ‘œνΌν‹°μ΄λ©°, ν•¨μˆ˜ 객체 고유의 ν”„λ‘œνΌν‹°κ°€ μ•„λ‹ˆλΌ Object.prototype 객체의 ν”„λ‘œνΌν‹°λ₯Ό 상속받은 것을 μ•Œ 수 μžˆλ‹€. Object.prototype 객체의 ν”„λ‘œνΌν‹°λŠ” λͺ¨λ“  객체가 μ‚¬μš©λ°›μ•„ μ‚¬μš©ν•  수 μžˆλ‹€.

18.2.1 arguments ν”„λ‘œνΌν‹°

arguments κ°μ²΄λŠ” ν•¨μˆ˜ 호좜 μ‹œ μ „λ‹¬λœ μΈμˆ˜λ“€μ˜ 정보λ₯Ό λ‹΄κ³  μžˆλŠ” 순회 κ°€λŠ₯ν•œ μœ μ‚¬ λ°°μ—΄ 객체이며, ν•¨μˆ˜ λ‚΄λΆ€μ—μ„œ 지역 λ³€μˆ˜μ²˜λŸΌ μ‚¬μš©λœλ‹€. 즉, ν•¨μˆ˜ μ™ΈλΆ€μ—μ„œλŠ” μ°Έμ‘°ν•  수 μ—†λ‹€.

μžλ°”μŠ€ν¬λ¦½νŠΈλŠ” ν•¨μˆ˜μ˜ λ§€κ°œλ³€μˆ˜μ™€ 인수의 κ°œμˆ˜κ°€ μΌμΉ˜ν•˜λŠ”μ§€ ν™•μΈν•˜μ§€ μ•ŠλŠ”λ‹€. λ”°λΌμ„œ ν•¨μˆ˜ 호좜 μ‹œ λ§€κ°œλ³€μˆ˜ 개수만큼 인수λ₯Ό μ „λ‹¬ν•˜μ§€ μ•Šμ•„λ„ μ—λŸ¬κ°€ λ°œμƒν•˜μ§€ μ•ŠλŠ”λ‹€.

ν•¨μˆ˜κ°€ 호좜되면 ν•¨μˆ˜ λͺΈμ²΄ λ‚΄μ—μ„œ μ•”λ¬΅μ μ˜€λ₯΄ λ§€κ°œλ³€μˆ˜κ°€ μ„ μ–Έλ˜κ³  undefined둜 μ΄ˆκΈ°ν™”λœ 이후 μΈμˆ˜κ°€ ν• λ‹Ήλœλ‹€.

// 예제 18-04
function multiply(x, y){
  console.log(arguments);
  return x + y;
}

console.log(multiply()); // NaN
console.log(multiply(1)); // NaN
console.log(multiply(1, 2)); // 2
console.log(multiply(1, 2, 3)); // 2

μ•„λž˜ 사진을 보면λͺ¨λ“  μΈμˆ˜λŠ” μ•”λ¬΅μ μœΌλ‘œ arguments 객체의 ν”„λ‘œνΌν‹°λ‘œ λ³΄κ΄€λ˜λŠ” 것을 λ³Ό 수 μžˆλ‹€. arguments κ°μ²΄λŠ” 인수λ₯Ό ν”„λ‘œνΌν‹° κ°’μœΌλ‘œ μ†Œμœ ν•˜λ©° ν”„λ‘œνΌν‹° ν‚€λŠ” 인수의 μˆœμ„œλ₯Ό λ‚˜νƒ€λ‚Έλ‹€.

κ°€λ³€ 인자 ν•¨μˆ˜λ₯Ό κ΅¬ν˜„ν•  λ•Œ 유용

arguments κ°μ²΄λŠ” λ§€κ°œλ³€μˆ˜ 개수λ₯Ό ν™•μ •ν•  수 μ—†λŠ” κ°€λ³€ 인자 ν•¨μˆ˜λ₯Ό κ΅¬ν˜„ν•  λ•Œ μœ μš©ν•˜λ‹€.

// 예제 18-06
function sum(){
  let res = 0;
  
  for(let i = 0; i < arguments.length; i++){
  	res += arguments[i];
  }
  return res;
}

console.log(sum()); // 0
console.log(sum(1, 2)); //3

μœ μ‚¬ λ°°μ—΄ κ°μ²΄λž€?
length ν”„λ‘œνΌν‹°λ₯Ό 가진 객체둜 for문으둜 μˆœνšŒν•  수 μžˆλŠ” 객체이닀.

arguments κ°μ²΄λŠ” μœ μ‚¬ λ°°μ—΄ 객체 μ΄λ©΄μ„œ μ΄ν„°λŸ¬λΈ”μ΄λ‹€. ν•˜μ§€λ§Œ 배열이 μ•„λ‹ˆλ―€λ‘œ λ°°μ—΄ λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•  경우 μ—λŸ¬κ°€ λ°œμƒν•œλ‹€. Function.prototype.callκ³Ό Function.prototype.applyλ₯Ό μ‚¬μš©ν•΄ κ°„μ ‘ ν˜ΈμΆœν•΄μ•Ό ν•˜λŠ” λ²ˆκ±°λ‘œμ›€μ΄ μžˆλ‹€. 이 λ²ˆκ±°λ‘œμ›€μ„ ν•΄κ²°ν•˜κΈ° μœ„ν•΄ ES6μ—μ„œλŠ” Rest νŒŒλΌλ―Έν„°λ₯Ό λ„μž…ν–ˆλ‹€.

// 예제 18-08
function sum(...args){
  return args.reduce((pre, cur) => pre + cur, 0); 
}

console.log(sum(1, 2, 3)); // 6

18.2.2 caller ν”„λ‘œνΌν‹°

caller ν”„λ‘œνΌν‹°λŠ” λΉ„ν‘œμ€€ ν”„λ‘œνΌν‹°μ΄κ³  μ•žμœΌλ‘œλ„ ν‘œμ€€ν™”λ  μ˜ˆμ •λ„ μ—†λŠ” ν”„λ‘œνΌν‹°μ΄λ―€λ‘œ 참고둜 μ•Œμ•„λ‘μž. ν•¨μˆ˜ 객체의 caller ν”„λ‘œνΌν‹°λŠ” ν•¨μˆ˜ μžμ‹ μ„ ν˜ΈμΆœν•œ ν•¨μˆ˜λ₯Ό 가리킨닀.

// 예제 18-09
function foo(func){
  return func();
}

function bar(){
  return 'caller : ' + bar.caller;
}

// λΈŒλΌμš°μ €μ—μ„œ μ‹€ν–‰ν•œ κ²°κ³Ό
console.log(foo(bar)); // caller : function foo(func) {...}
console.log(bar()); //caller : null

μœ„ κ²°κ³ΌλŠ” λΈŒλΌμš°μ €μ—μ„œ μ‹€ν–‰ν•œ 결과이고 node.js ν™˜κ²½μ—μ„œ μ‹€ν–‰ν•˜λ©΄ λ‹€λ₯Έ κ²°κ³Όκ°€ λ‚˜μ˜¨λ‹€.

18.2.3 length ν”„λ‘œνΌν‹°

ν•¨μˆ˜ 객체의 length ν”„λ‘œνΌν‹°λŠ” ν•¨μˆ˜λ₯Ό μ •μ˜ν•  λ•Œ μ„ μ–Έν•œ λ§€κ°œλ³€μˆ˜μ˜ 개수λ₯Ό 가리킨닀.

//예제 18-10
function foo(){}
console.log(foo.length); // 0

function bar(x){
  return x;
}
console.log(bar.length); // 1

function baz(x, y){
  return x * y;
}
console.log(baz.length); // 2

arguments 객체의 length ν”„λ‘œνΌν‹°μ™€ ν•¨μˆ˜ 객체의 length ν”„λ‘œνΌν‹° 값은 λ‹€λ₯Ό 수 μžˆμœΌλ―€λ‘œ μ£Όμ˜ν•΄μ•Όν•œλ‹€. ν•¨μˆ˜ 객체의 length ν”„λ‘œνΌν‹°λŠ” λ§€κ°œλ³€μˆ˜μ˜ 개수λ₯Ό 가리킨닀.

18.2.4 name ν”„λ‘œνΌν‹°

ν•¨μˆ˜ 객체의 name ν”„λ‘œνΌν‹°λŠ” ν•¨μˆ˜ 이름을 λ‚˜νƒ€λ‚Έλ‹€. name ν”„λ‘œνΌν‹°λŠ” ES6μ—μ„œ 정식 ν‘œμ€€μ΄ λ˜μ—ˆλ‹€. ES5μ—μ„œλŠ” 빈 λ¬Έμžμ—΄μ„ κ°’μœΌλ‘œ κ°–μ§€λ§Œ ES6μ—μ„œλŠ” ν•¨μˆ˜ 객체λ₯Ό κ°€λ¦¬ν‚€λŠ” μ‹λ³„μžλ₯Ό κ°’μœΌλ‘œ κ°–λŠ”λ‹€.

// 예제 18-11
var nameFunc = function foo(){};
console.log(namedFunc.name); // foo

var anonymousFunc = function(){};
console.log(anonymousFunc.name); // anonymousFunc

function var(){}
console.log(bar.name); // bar

18.2.5 proto μ ‘κ·Όμž ν”„λ‘œνΌν‹°

λͺ¨λ“  κ°μ²΄λŠ” [[Prototype]]μ΄λΌλŠ” λ‚΄λΆ€ μŠ¬λ‘―μ„ κ°–λŠ”λ‹€. __proto__ ν”„λ‘œνΌν‹°λŠ” [[Prototype]] λ‚΄λΆ€ 슬둯이 κ°€λ¦¬ν‚€λŠ” ν”„λ‘œν† νƒ€μž… 객체에 μ ‘κ·Όν•˜κΈ° μœ„ν•΄ μ‚¬μš©ν•˜λŠ” μ ‘κ·Όμž ν”„λ‘œνΌν‹°μ΄λ‹€. λ‚΄λΆ€ μŠ¬λ‘―μ—λŠ” 직접 μ ‘κ·Όν•  수 μ—†κ³  간접적인 μ ‘κ·Ό 방법을 μ œκ³΅ν•˜λŠ” κ²½μš°μ— ν•œν•˜μ—¬ μ ‘κ·Όν•  수 μžˆλ‹€.

// 예제 18-12
const obj = { a: 1 };

// 객체 λ¦¬ν„°λŸ΄ λ°©μ‹μœΌλ‘œ μƒμ„±ν•œ 객체의 ν”„λ‘œν„°νƒ€μž… κ°μ²΄λŠ” Object.prototype이닀.
console.log(obj.__proto__ === Object.prototype); // true

// 객체 λ¦¬ν„°λŸ΄ λ°©μ‹μœΌλ‘œ μƒμ„±ν•œ κ°μ²΄λŠ” ν”„λ‘œν† νƒ€μž… 객체인 Object.prototype의 ν”„λ‘œνΌν‹°λ₯Ό μƒμ†λ°›λŠ”λ‹€.
// hasOwnProperty λ©”μ„œλ“œλŠ” Object.prototype의 λ©”μ„œλ“œμ΄λ‹€.
console.log(obj.hasOwnProperty('a')); // true
console.log(obj.hasOwnProperty('__proto__'));

hasOwnProperty λ©”μ„œλ“œ

인수둜 전달받은 ν”„λ‘œνΌν‹° ν‚€κ°€ 객체 고유의 ν”„λ‘œνΌν‹° 킀인 κ²½μš°μ—λ§Œ trueλ₯Ό λ°˜ν™˜ν•˜κ³  상속받은 ν”„λ‘œν† νƒ€μž… ν”„λ‘œνΌν‹° 킀인 경우 falseλ₯Ό λ°˜ν™˜ν•œλ‹€.

18.2.6 prototype ν”„λ‘œνΌν‹°

μƒμ„±μž ν•¨μˆ˜λ‘œ ν˜ΈμΆœν•  수 μžˆλŠ” ν•¨μˆ˜ 객체, 즉 constructor만이 μ†Œμœ ν•˜λŠ” ν”„λ‘œνΌν‹°μ΄λ‹€. 일반 객체와 μƒμ„±μž ν•¨μˆ˜λ‘œ ν˜ΈμΆœν•  수 μ—†λŠ” non-constructorμ—λŠ” prototype ν”„λ‘œνΌν‹°κ°€ μ—†λ‹€.

// 예제 18-13
(function () {}).hasOwnProperty('prototype'); // true

({}).hasOwnProperty('prototype'); // false

prototype ν”„λ‘œνΌν‹°λŠ” ν•¨μˆ˜κ°€ 객체λ₯Ό μƒμ„±ν•˜λŠ” μƒμ„±μž ν•¨μˆ˜λ‘œ 호좜될 λ•Œ μƒμ„±μž ν•¨μˆ˜κ°€ 생성할 μΈμŠ€ν„΄μŠ€μ˜ ν”„λ‘œν† νƒ€μž… 객체λ₯Ό 가리킨닀.

Ref

  • 이웅λͺ¨ μ €, ⌜λͺ¨λ˜ μžλ°”μŠ€ν¬λ¦½νŠΈ Deep Dive⌟, μœ„ν‚€λΆμŠ€
profile
맀 μˆœκ°„ μ„±μž₯ν•˜λŠ” κ°œλ°œμžκ°€ 되렀고 λ…Έλ ₯ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€.

0개의 λŒ“κΈ€