일급 객체
일급 객체의 조건
- 익명 리터럴을 런타임에 생성 가능
- 변수나 자료구조에 저장 가능
//변수
const foo = function() {
console.log("foo");
}
const bar = function() {
console.log("bar");
}
foo(); //foo
bar(); //bar
//객체
const obj = { foo, bar };
console.log(obj); //{ foo: [Function: foo], bar: [Function: bar] }
//배열
const arr = [foo, bar];
console.log(arr[0]); //[Function: foo]
3. 함수의 매개변수에 전달 가능
function sayHello() {
return "Hello, ";
}
function greeting(helloMessage, name) {
console.log(helloMessage() + name);
}
// sayHello를 greeting 함수에 인자로 전달
greeting(sayHello, "JavaScript!");
4. 함수의 반환 값으로 사용 가능
function sayHello() {
return function() {
console.log("Hello!");
}
}
- 익명 함수 호출
//반환된 함수 다른 변수에 저장
const sayHello = function() {
return function() {
console.log("Hello!");
}
}
const myFunc = sayHello();
myFunc();
- sayHello 를 직접 호출하면, 반환된 함수를 호출하지 않고 함수 자체를 반환
- 따라서 다른 변수에 저장하여 사용
//이중 괄호 사용
function sayHello() {
return function() {
console.log("Hello!");
}
}
sayHello()();
함수 객체의 프로퍼티
- 일반 객체에 없는 함수 객체 고유의 프로퍼티
- __proto__ 는 예외적으로 함수 객체 고유의 프로퍼티가 아니라 Object.prototype 객체의 프로퍼티를 상속받는다.
function square(number) { return number * number; }
//square 함수의 프로퍼티 어트리뷰트 확인
console.log(Object.getOwnPropertyDescriptors(square));
/*
{
length: {value: 1, writable: false, enumerable: false, configurable: true},
name: {value: "square", writable: false, enumerable: false, configurable: true},
arguments: {value: null, writable: false, enumerable: false, configurable: false},
caller: {value: null, writable: false, enumerable: false, configurable: false},
prototype: {value: {...}, writable: true, enumerable: false, configurable: false}
}
*/
//__proto__는 함수의 프로퍼티가 아니라 Object.prototype 객체의 접근자 프로퍼티
console.log(Object.getOwnPropertyDescriptors(square, '__proto__')); // undefined
arguments 프로퍼티
function func1(a, b, c) {
console.log(arguments[0]);
console.log(arguments[1]);
console.log(arguments[2]);
}
func1(1, 2, 3);
func1(1, 2);
func1(1, 2, 3, 4);
- 함수 호출 시 전달된 인수들의 정보를 담고 있는 순회 가능한 유사 배열 객체
- 함수 내부에서 지역 변수처럼 사용 가능
- 매개변수 개수와 인수 개수가 달라도 에러가 발생하지 않는다.
- 매개변수 개수 > 인수 개수: undefined 초기화
- 매개변수 개수 < 인수 개수: 초과된 인수 무시
- 유사 배열 객체이므로 for 문으로 순회 가능
구성
arguments.callee
- 현재 실행 중인 함수
- ES5 에서는 strict mode 에서의 사용을 금지
arguments.length
- 함수에 전달된 인수의 수
- 가변 인자 함수를 구현할 때 유용
//가변 인자 함수
function sum() {
let res = 0;
for(let i = 0; i < arguments.length; i++){
res += arguments[i]
}
return res;
}
console.log(sum());
console.log(sum(1, 2));
console.log(sum(1, 2, 3));
arguments.Symbol
- arguments 객체를 순회 가능한 자료구조인 이터러블로 만들기 위한 프로퍼티
function multiply(x, y) {
const iterator = arguments[Symbol.iterator]();
console.log(iterator.next()); // {value: 1, done: false}
console.log(iterator.next()); // {value: 2, done: false}
console.log(iterator.next()); // {value: 3, done: false}
console.log(iterator.next()); // {value: undefined, done: true}
return x * y;
}
console.log(multiply(1, 2, 3));
유사 배열 객체
- 배열처럼 보이지만 key가 숫자이고, length 값을 가지고 있는 객체
- 배열 메서드를 사용할 수 없다.
//배열
array = [1, 2, 3];
array.forEach(function (el) { console.log(el); }); // 1, 2, 3
//유사 배열 객체
notArray = {
0: 'Hi',
1: 'My',
2: 'name',
}
console.log(notArray[0]); //Hi
console.log(notArray[0].length); //2
console.log(notArray.length);
notArray.forEach(function (el) { console.log(el); }); // Error
배열로 만들려면?
- Array.from()
- 유사 배열 객체나 반복 가능 객체의 value를 얕은 복사해서 배열로 만드는 메서드
console.log(Array.from('foo')); // Array ["f", "o", "o"] console.log(Array.from([1, 2, 3], x => x + x)); //Array [2, 4, 6]
배열 메서드를 사용하고 싶다면?
- Function.prototype.apply
function.apply(thisArg, argsArray)
- thisArg 를 this 객체에 바인딩하고 전달 받은 인자를 arguments 에 설정한 후 해당 함수 호출
- arguments 를 배열로 전달
- strict mode 가 아닌 경우 null 과 undefined 가 전역 객체로 대체
반환 값
- 지정된 this 값과 인수로 함수를 호출한 결과
Math.max(5, 6, 2, 3, 7);
var numbers = [5, 6, 2, 3, 7];
Math.max.apply(null, numbers); //7
- Function.prototype.bind
function.bind(thisArg, arg1, arg2, ...)
- 첫 번째 인자를 this 에 바인딩하고, 두 번째 인자부터 arguments 를 순서대로 전달
- 전달된 arguments 를 미리 부분 적용한 함수를 리턴
- Function.prototype.call
function.call(thisArg, arg1, arg2, ...)
- thisArg 를 this 객체에 바인딩하고 전달 받은 인자를 arguments 에 설정한 후 해당 함수 호출
- arguments 를 순서대로 전달
caller 프로퍼티
- 지정된 함수를 호출한 함수를 반환
- strict mode 에서는 오류 발생
- 웹 표준에서 이미 제거된 프로퍼티. 사용 권장하지 않음
function foo(func) {
return func();
}
function bar() {
return 'caller : ' + bar.caller;
}
console.log(foo(bar)); // caller: function foo(func) {...}
console.log(bar()); // caller: null
- foo(bar) 에서 bar 함수를 호출한 함수는 foo 이므로 caller: foo
- bar() 에서 bar 함수를 호출한 함수는 존재하지 않으므로 null
length 프로퍼티
- 함수를 정의할 때 선언한 매개변수의 개수
arguments.length vs Function.length
- arguments.length
//인자의 개수를 가리킴
function func1(a, b) {
console.log(arguments.length); // 2
return a * b;
}
- Function.length
//매개 변수의 개수를 가리킴
function func1() {}
function func2(a) {}
function func3(a, b) {}
console.log(func1.length); // 0
console.log(func2.length); // 1
console.log(func3.length); // 2
- Writable(변경 가능): no
- Enumerable(열거 가능): no
- Configurable(재정의 가능): yes
name 프로퍼티
- 함수 이름
- 익명 함수의 경우 함수 객체를 가리키는 변수 이름을 값으로 가짐
//기명함수
var namedFunc = function foo() {};
console.log(namedFunc.name); // foo
//익명함수
var anonymousFunc = function() {};
console.log(anonymousFunc.name); // anonymousFunc
__proto__ 접근자 프로퍼티
- 내부 슬롯이 가리키는 프로토타입([[Prototype]] 내부 슬록) 에 간접적으로 접근하기 위해 사용하는 접근자 프로퍼티
- 사용 이유는 상호 참조에 의해 프로토타입 체인이 생성되는 것을 방지
- 객체 리터럴 방식으로 생성한 객체는 프로토타입 객체인 Object.prototype 을 상속받는다.
- hasOwnProperty 메서드는 Object.prototype의 메서드이다.
const obj = { a: 1 };
console.log(obj.__proto__ === Object.prototype);
//해당 인수가 객체 고유의 프로퍼티 키인 경우 true
//상속받은 프로토타입의 프로퍼티 키인 경우 false
console.log(obj.hasOwnProperty('a')); //true
console.log(obj.hasOwnProperty('__proto__')); //false
hasOwnProperty()
- 객체가 특정 프로퍼티를 가지고 있는지 여부를 나타내는 메서드
__proto__ 대신 사용할 수 있는 메서드
1. Object.create(proto, [descriptors])
- [[Prototype]] 이 proto 를 참조하는 빈 객체를 만든다.
2. getPrototypeOf(obj)
- __proto__ 에서 대체된 메서드
- 지정된 객체의 [[Prototype]]를 반환
- 매개변수가 객체가 아닌 경우 에러가 발생
3. Object.setPrototypeOf(obj, proto)
- 지정된 객체의 [[Prototype]] 이 proto 가 되도록 설정
let animal = {
eats: true
};
// 프로토타입이 animal인 새로운 객체를 생성
let rabbit = Object.create(animal);
console.log(rabbit.eats); // true
console.log(Object.getPrototypeOf(rabbit) === animal); //true
Object.setPrototypeOf(rabbit, {}); // rabbit의 prototype을 {}로 바꾼다.
prototype 프로퍼티
- 생성자 함수로 호출할 수 있는 함수 객체
- constructor 만이 소유하는 프로퍼티
- 함수 객체가 생성자로 사용될 때 이 함수를 통해 생성될 객체의 프로토타입 객체를 가리킨다.
- Writable(변경 가능): yes
- Enumerable(열거 가능): no
- Configurable(재정의 가능): no
//함수 객체(constructor)
(function () {}).hasOwnProperty('prototype'); // true
//일반 객체(non-constructor)
({}).hasOwnProperty('prototype'); //false
let animal = {
eats: true
};
function Rabbit(name) {
this.name = name;
}
Rabbit.prototype = animal;
let rabbit = new Rabbit("White Rabbit");
// rabbit.__proto__ == animal
'Frontend > JavaScript' 카테고리의 다른 글
[JavaScript] 제너레이터와 async/await (0) | 2023.02.16 |
---|---|
[JavaScript] DOM 이벤트 (0) | 2023.02.16 |
[JavaScript] Set (2) | 2023.02.16 |
[JavaScript] 이터러블 (1) | 2023.02.16 |
[JavaScript] 객체 리터럴 (1) | 2022.11.08 |