Function 타입
ECMAScript에서 함수는 사실 객체입니다.
모든 함수는 Function 타입에 대한 인스턴스이며 다른 참조 타입과 마찬가지로 프로퍼티/메서드가 있습니다
함수를 정의하는 방법
function sum (num1, num2) {
return num1 + num2;
}
- 함수 선언 방식
함수 선언 호이스팅 과정으로 인하여 함수 선언부를 다른 코드를 실행하기전에 먼저 읽고 모든 실행 컨텍스트에서 접근하고 실행할 수 있습니다.
** 함수 선언 호이스팅(hoisting)
JS 엔진은 코드를 평가할 때 제일 먼저 함수 선언을 찾은 다음 이들을 맨 위로 올립니다.
함수가 선언된 부분이 함수가 실행되는 부분보다 뒤에 있을 경우에도 JS 엔진이 함수 선언을 '끌어올립니다 hoist'.
const sum = function (num1, num2) {
return num1 + num2;
}
- 함수 표현식
함수 표현식은 자바스크립트 프로그래밍에서 유용한 도구입니다.
함수 표현식은 일반적인 변수 할당과 비슷하게, 함수가 선언 되기 이전 줄에서 사용할 수 없습니다.
람다함수, 익명함수 라고 불리기도하며, 함수에 꼭 이름이 필요하지 않게 함으로써 동적인 프로그래밍을 가능하게 합니다.
함수 표현식에 대한 자세한 사용 방법 및 참고는 여기를 참고해주세요.
함수의 내부 구조
함수에는 arguments , this 라는 특별한 객체가 있습니다.
-
arguments객체는 배열과 비슷한 객체이며, 함수에 전달된 매개변수를 모두 표현합니다.(현재 MDN에선 권장하지 않습니다.) -
arguments 의 '소유자인 함수'를 가리키는 포인터인 arguments.callee 라는 프로퍼티도 있습니다.(strict 모드 에서는 사용을 금합니다.) -
함수 객체내부에 존재하는 caller 프로퍼티도 있습니다. 해당 함수를 호출한 함수에 대한 참조를 저장하며, 스코프에서 호출했다면 null 이 저장됩니다.(현재 MDN에선 권장하지 않습니다.)
함수 프로퍼티와 메서드
모든 함수에 공통인 프로퍼티는 length , prototype 입니다.
-
length : 함수가 넘겨 받을 것으로 예상하는 매개변수의 갯수를 의미합니다.
-
prototype : 모든 참조 타입의 기본적인 인스턴스 메서드가 존재하는 곳
개발자가 정의한 참조 타입과 상속을 정의할 때 가장 중요합니다.
함수는 apply() , call() , bind() 라는 메서드들을 보유하고있습니다.
이 메서드들은 해당 함수를 호출한 '함수의 소유자 객체(owner object)' 를 호출하면서 소유자 object의 this 를 넘길 수 있습니다.
말하자면 소유자 object는 this 의 주체를 가리킨다고 할 수 있습니다. 결과적으로는 함수 내부에서 this 객체의 값을 바꾸는 것이나 마찬가지입니다.
-
call() : 함수에 call() 메서드를 사용하므로써 특정 object에서 다른 object에 정의되어있는 메서드를 사용할 수 있게 해줍니다.
해당 함수의 소유자 object를 매개변수로 하여 메서드를 호출할 수 있습니다. 소유자 Object가 필요하지 않다면 null을 할당 할 수 있습니다.
const person = {
fullName: function() {
return this.firstName + " " + this.lastName;
}
}
const person1 = {
firstName: "Jan",
lastName: "Ding"
}
const person2 = {
firstName: "Mary",
lastName: "Ding"
}
person.fullName.call(person2) // "Mary Ding"
person.fullName.call(person1) // "Jen Ding"
두 번째 이후 매개변수에는 필요한 내용들을 각각 나열하면 됩니다.
- 매개변수 ( 함수에 넘길 소유자 object의 this , 사용할 매개변수 각각 나열 )
// 매개변수와 함께 사용시
const person = {
fullName: function (city, country) {
return
this.firstName + " " + this.lastName + "," + city + "," + country
}
}
const person1 = {
firstName: "Jen",
lastName: "Ding"
}
person.fullName.call(person1, "Seoul", "Korea");
// "Jen Ding, Seoul, Korea"
-
apply() : apply는 call 메서드와 비슷하게 동작하지만, 매개변수를 전달하는 방식만 다릅니다.
- 매개변수 ( 소유자 함수에 넘길this, 매개변수만으로 이루어진배열 )
// 매개변수와 함께 사용시
const person = {
fullName: function (city, country) {
return
this.firstName + " " + this.lastName + "," + city + "," + country
}
}
const person1 = {
firstName: "Jen",
lastName: "Ding"
}
person.fullName.apply(person1, ["Seoul", "Korea"]);
// "Jen Ding, Seoul, Korea"
두 메서드는 소유자 객체 - this 를 바꾸는데에 가장 효과적으로 사용할 수 있습니다.
window.color = "red";
const o = { color: "blue" };
function sayColor() {
console.log(this.color)
}
sayColor(); // red -> owner object :: Window
sayColor.call(this) // red -> owner object :: Window
sayColor.call(window) // red -> owner object :: Window
sayColor.call(o) // blue -> owner object :: o
전역 함수로 정의된 sayColor() 는 전역 scope에서 호출하면 this.color 를 window.color 로 평가하여 'red'를 표시합니다.
call() 이나 apply() 를 써서 scope를 바꾸면 객체마다 일일히 같은 메서드를 등록하지 않아도 된다는 장점이 있습니다.
- bind() : 이 메서드를 사용하면 함수의 this 는 bind() 에 전달된 object로 고정되어 해당 object를 가리킵니다.
const o = { color: 'blue' }
function sayColor () {
console.log(this.color)
}
const objectSayColor = sayColor.bind(o);
// bind() 로 인해 sayColor 함수는 객체 o 로 고정됩니다.
// sayColor의 this는 지금부터 o를 가리킵니다.
objectSayColor(); // 'blue'
bind() 는 특정 객체나 class안에 정의된 메서드에서도 바인딩 할 수 있습니다.
class SayColor {
constructor (a, b) {
this.a = a
this.b = b
}
colorType () {
console.log('this is: ', this)
console.log(`a is..${this.a}, b is..${this.b}`)
}
}
const o = { a: 'pink', b: 'salmon' }
const color = new SayColor('red', 'blue')
color.colorType()
// this is.. SayColor { a: "red", b: "blue" }
// "a is..red, b is.. blue"
color.colorType.bind(o)()
// this is.. { a: "pink", b: "salmon" }
// a is..pink, b is.. salmon
this 는 이미 sayColor object에 binding 되어있는 상태지만, 그 위에 새로 o object로 새로 binding을 할 수 있습니다.
Arrow Function
Arrow Function은 일반 Function과 비슷하게 동작하지만, 문법 / 바인딩 등에서 차이점이있습니다.
문법은 생략하고 그 외 차이점에 대해 확인해 보겠습니다.
1. arguments 바인딩
Arrow Function은 arguments 객체에 대한 바인딩(매개변수 전체에 접근)이 없습니다. 다시말해, arguments 사용이 불가능합니다.
// Regular Function
const foo = {
showArgs () {
console.log(arguments)
}
}
foo.showArgs(1, 2, 3, 4); // 1, 2, 3, 4
// Arrow Function
const foo = {
showArgs: () => {
console.log( ...arguments )
}
}
foo.showArgs(1, 2, 3, 4) // Error: arguments is not defined
2. this 의 사용
Arrow Function의 this 의 값은 상위 scope의 this 를 가리킵니다. (Lexical this 라고 합니다)
const aboutMe = {
name: "JJ",
thisInArrow: () => {
console.log("My name is " + this.name)
// no 'this' binding here
},
thisInRegular () {
console.log("My name is " + this.name)
// 'this' binding works here
}
}
aboutMe.thisInArrow() // My name is -> window object
aboutMe.thisInRegular() // My name is JJ
3. new 키워드의 사용
선언함수나 함수 표현식으로 생성된 일반 Function은 생성과 호출이 모두 가능합니다. 일반 Function은 생성(construct)할 수 있기 때문에, new 키워드를 사용하면서 생성자 함수로쎠 호출될 수 있습니다.
그러나, Arror Function은 호출은 가능하지만 생성될 수는 없기 때문에 constructor function으로서 사용될 수 없습니다. 그러므로, new 키워드를 사용하여 호출될 수 없습니다.
const add = (x, y) => console.log(x + y);
new add(2, 3)
// Error: add is not a constructor
4. 이름이 동일한 매개변수 사용 불가능
(물론 사용할일은 없겠지만,) Arrow Function은 strict 모드에서든 일반모드에서든, 이름이 같은 매개변수(named parameters)를 절대 사용할 수 없습니다.
const add (x, x) => {}
// SyntaxError: duplicate argument names not allowed in this context
** 일반 Function 에서는, 일반모드일 때만 이름이 동일한 매개변수를 사용할 수 있습니다. (strict 모드 불가능)
참고 : medium.com/better-programming/difference-between-regular-functions-and-arrow-functions-f65639aba256
pure function
'FRONTEND > Javascript' 카테고리의 다른 글
Javascript의 프로토타입 (0) | 2020.09.03 |
---|---|
Javascript의 this (0) | 2020.08.19 |
참조타입 (0) | 2020.07.29 |
웹 브라우저의 메모리 관리 - 가비지 컬렉션(Garbage Collection) (0) | 2020.07.29 |
LocalStorage & SessionStorage (0) | 2020.05.09 |
댓글