어리바리 신입 개발자의 얼렁뚱땅 개발 기록 ✨
23.03.30 / 함수 function 본문
728x90
{ 함수 }
- 메모리에 코드를 저장 할 수 있는 수단
- function이라는 키워드를 사용하여 선언이 가능하다.
- 함수는 선언 후에 호출이 되어야 저장된 코드가 실행된다. (단, 일반함수는 선언 전에 호출 가능)
- 함수에는 일반함수와 익명함수가 존재한다.
- 함수를 하나 선언해 두면 굳이 코드를 반복해서 사용할 필요 없이 함수를 호출만 하면 된다.
- return 키워드를 만나면 함수는 종료 된다. - return 없으면 undefined (return 변수; / return; 형태 둘 다 사용 가능)
- return 키워드와 값을 지정하게 되면 함수를 호출한 곳에 그 값을 전달하게 한다.
function returnCall(n1, n2){
return n1 + n2; //리턴하려는 값
}
//호출한 곳에 값을 전달
var result = returnCall(10,20); // n1 + n2 의 값인 30이 출력된다.
console.log(result);
[ 함수와 메서드의 차이 ]
- 객체의 구성 : 속성 / 메서드
객체 내에서 함수를 선언하는 것을 기능/동작/메서드(데이터를 참조하고 조작할 수 있음)라고 한다.
▶ 메서드의 구성 -> 메서드명(매개변수명-생략가능) {구현}
객체 내에서 함수 외의 것을 선언하는 것을 데이터/속성/프로퍼티라고 한다.
▶ 속성/프로퍼티의 구성 -> 키 : 값
즉, 객체에 생성된 함수를 메서드라고 한다.
[ 자바스크립트에서 함수의 특징 - 일급객체/일급함수 / 객체지향형 & 함수형]
- 자바스크립트에서 객체는 일급 객체다.
- 자바스크립트에서 함수는 객체이기 때문에 일급 객체 / 일급 함수다.
일급 함수란 ?
함수를 다른 함수의 매개변수로 전달이 가능하거나, 변수에 담을 수도 있고, 인자나 값으로도 사용이 가능한 함수
- 참조 값을 사용할 수 있는 곳이라면 어디든지 사용 가능무명의 리터럴(익명함수)로 생성할 수 있다. 즉, 런타임(실행시점)에 생성이 가능하다. (자바에서도 비슷하게 생성은 가능)
- 변수나 자료구조(객체, 배열 등)에 저장할 수 있다. (배열 안에 어떠한 형태든 다 저장할 수 있다. - 자바는 안 됨 데이터 타입 정해져 있기 때문 / 즉, 자바는 일급함수 일급객체 x )
- 함수의 매개변수에 전달할 수 있다.
- 함수의 반환값으로 사용할 수 있다.
이런 특징이 함수형 프로그래밍을 가능하게 함
(객체지향형 프로그래밍 - 자바 / 자바스크립트는 객체지향형,함수형 둘 다 지니고 있음)
프로그래밍의 발전 순서
절차지향형 프로그래밍(c) -> 객체지향형 프로그래밍(java) -> 객체지향형 & 함수형 프로그래밍(java script)
자바스크립트는 객체지향형 프로그래밍의 형태 역시 지니고 있지만 class 존재하지 않는다.
상속,추상화,다형성은 존재 - 사실 상속되는 것은 아니고 prototype으로 연결해서 상송을 받는 척 한다. (추상화와 다형성도 마찬가지)
자바에서 class를 통해 객체를 생성한다고 배웠는데 class가 없는데 어떻게 객체를 만들어? - 그냥 class 없이 만들어
// 클래스 없이 바로 객체 생성 let obj = { name : '홍길동', arr : [] }이와 같이 자바스크립트는 객체지향형과 함수형 프로그래밍을 섞어 사용하고 있다.
// 객체지향 프로그래밍 (자바) // car라는 객체를 생성 // 객체 car의 주소로 찾아가 start 메서드와 move 메서드를 호출한다. // 객체 중심 car.start(); car.move(10); // 함수형 프로그래밍 (자바스크립트) // 객체 생성 x (자바스크립트에서 객체 생성은 let obj = {}) // 함수 중심 start(car); move(car, 10);
[ 함수 선언 ]
- function 함수명(){}
- {} - 스코프 (블럭, 유효범위)
- 함수는 지역변수와 전역변수의 차이가 확실하다.
[ 자바스크립트의 매개변수 / 오버로딩 ]
- 자바와 다르게 자바스크립트의 매개변수는 자유롭게 사용한다. (데이터 타입 없어도 됨 - java : String name / js : name)
- 자바와 다르게 함수의 오버로딩 불가능
※ 자바스크립트의 오버로딩(불가능) ※
- 함수가 동일한 이름으로 선언됐을 때
- 평가 시점에 위의 함수와 아래 함수가 동시에 호이스팅 됨
- 이름이 같기 때문에 가장 아래에 선언된 함수로 덮어 씌워짐
- 때문에 1번 호출에서 최종적으로 호출1과 undefined를 콘솔에 출력한다.
- 여기서 undefined는 1번 리턴이 아닌 2번 리턴의 결과(호이스팅에서 덮어 씌워졌기 때문)
- 2번 호출을 통해서는 호출1이 콘솔에 출력되고 끝난다.
왜 1번 호출에서는 호출1과 undefined 까지 출력됐는데 2번 호출에서는 호출1만 출력되고 끝난걸까?
- 1번 호출에서는 return 값을 콘솔에 출력할 수 있는 콘솔로그 안에서 함수가 호출 되었고
- 2번 호출에서는 return 값을 콘솔에 출력할 수 있는 콘솔로그 없이 단독으로 함수가 호출 되었기 때문
function returnTestFn(){
return; // 1번 리턴
}
console.log(returnTestFn(), '1번 호출');
// 아래 동명의 함수가 선언되기 전에는 1번 리턴값 undefined 출력
// 동명의 함수 재선언(오버로딩) - 결과적으로 불가능
function returnTestFn(){
console.log('호출1');
return; // 2번 리턴
console.log('호출2');
}
returnTestFn(); // 2번 호출
------------------------------------------------------------------------------------
※ 자바의 오버로딩(가능) ※
void overload(){
System.out.println("매개변수 없음");
}
void overload(Strin name, int age){
System.out.println("매개변수" + name + age + "총 두 개");
}
void overload(char gender){
System.out.println("매개변수" + gender + "한 개");
}
overload();
overload("홍길동", 8);
overload('남');
// 선언 당시 입력된 매개변수에만 맞게 호출해주면 동명 메서드도 선언 가능하고
// 출력도 다 다르게 나온다.
[ 함수의 종류 ]
< 1. 일반 함수 >
함수명 있음, 호이스팅 O -> 선언부 위에서 호출 가능
fn(); // 선언 전에 호출 가능
function fn(){ // 함수 이름 존재
console.log('일반함수 실행');
}
fn(); // 선언 후에 호출하는 것도 당연히 가능
< 2. 익명 함수 >
함수명 없음 -> 변수 선언/할당해서 대신 사용 가능 , 호이스팅 X -> 선언부 위에서 호출 불가능
fn1(); //호이스팅 x (평가 시점에 함수 할당 x / 실행 시점에 함수 할당 o) -> 선언 전에 호출 불가능
const fn1 = function(){ // 익명함수는 함수명이 존재하지 x - 대신 변수에 대입해서 사용
console.log('익명함수 실행');
}
fn1(); // 선언 후에 호출하는 것은 당연히 가능
//화살표 함수 선언 ( 익명함수의 일종이기 때문에 호이스팅 x )
arrFn1(); // 호이스팅 x
arrFn2();
const arrFn1 = () => {
console.log('화살표함수1 실행');
}
const arrFn2 = () => console.log('화살표함수2 실행'); // 코드가 하나일 때 한 줄로 쓰기 가능
arrFn1();
arrFn2();
[ 화살표 함수 이해하기 ]
화살표 함수 쓰는 이유
1. 함수를 짧게 쓸 수 있음
(매개변수) => 표현식;
2. 자바스크립트에서는 함수를 생성하고 그 함수를 어딘가에 전달하는 것이 자연스러움
그런데 어딘가에 함수를 전달하게 되면 함수의 컨텍스트(함수 동작에 필요한 정보를 담은 객체)를 잃을 수 있다.
이럴 때 화살표 함수를 사용하면 현재 컨텍스트를 잃지 않아 편리
- 컨텍스트? 코드의 흐름/문맥이나 함수 동작에 필요한 환경 정보가 담긴 객체
화살표 함수의 특징
1. 익명 함수
2. 생성자로 사용할 수 없다.
3. 자기 자신의 this를 갖지 않는다. - 함수가 정의된 스코프에 존재하는 this를 가리킨다.
(객체 안에 있는 메서드의 내부 함수에서 this를 사용하면 속한 객체의 this가 아닌 전역 객체의 this를 가리킴)
즉, 컨텍스트를 잃을 수 있음. [this 자세하게 보기]
4. 생성될 때 this 가 결정된다.
5. 화살표 함수가 어떻게 사용되건, 호출되건, this가 가리키는 것은 바뀌지 않는다.
6. return하지 않아도 값이 반환된다. ( 중괄호 사용시 return 해야함 )
// 기본 익명함수를 사용했을 때 // 내부함수의 this는 자신이 속한 객체를 가리키지 않고 전역 객체를 가리키기 때문에 // this.name은 존재하지 않는다. (전역 스코프에 선언된 name 없음) const cat = { name: 'meow', sound: function() { let sound2 = function() { console.log(this.name); } sound2(); } }; cat.sound(); // undefined // 이 때 화살표 함수로 바꿔주면 this는 무조건 함수가 정의된 스코프의 객체를 가리키기 때문에 // meow를 출력한다. const cat = { name: 'meow', sound: function() { let sound2 = () => console.log(this.name); sound2(); } }; cat.sound(); // meow 출력
// 기본 익명함수 let func = function(arg1, arg2, ...argN) { return expression; }; // 화살표 함수 (위의 기본 익명함수와 같은 코드) // function 생략 , 화살표 입력 // let func = 는 변수에 할당해서 대신 사용해주는 방법이다. // 즉 화살표 함수의 구조는 사실 (매개변수) => 표현식; 이다. let func = (arg1, arg2, ...argN) => expression; let func = (arg1, arg2, ...argN) => (expression); let func = (arg1, arg2, ...argN) => {return expression}; // 받을 인수가 없는 경우 매개변수 자리 비워두는 것도 가능 // 단, 괄호 생략 불가 let func = () => expression; // 단, 매개변수가 하나일 때 괄호 생략 가능 (매개변수가 없거나 두 개 이상이면 무조건 괄호 씀) let func = arg => expression; // 표현식이 여러 줄 일 경우 {} 사용 // 중괄호를 쓸 때는 반환할 값에 return 표시 해야함. let func = () => { expression1; return expression2; }; // 화살표 함수에서 객체 리턴하기 const arrowObj = () => ({}) const arrowObj = () => {return{}} let : 변수 선언 키워드 func : 변수 이름 (화살표 함수는 익명함수기 때문에 변수에 할당) arg1, arg2, ...argN : 매개변수 expression : 표현식 매개변수에 인자 값을 받아 표현식을 평가하고 평가 결과를 "반환 return"한다.
[ 함수 복사 ]
const func1 = function(){
console.log('익명함수 func1 실행');
}
const arrowFn3 = () => {
console.log('익명함수(화살표 함수) arrowFn3 실행');
}
let copyFn1 = func1; // 함수는 객체 타입이기 때문에 주소 복사 가능 (얕은 복사)
let copyFn2 = arrowFn3;
copyFn1();
copyFn2();
console.log(copyFn1 == func1, '복사한 함수 같은 주소 여부 확인');
console.log(typeof copyFn1, '<- function의 타입'); //function 타입 연산 시 function 문자열 반환
console.log(typeof null, '<- null의 타입'); //null 타입 연산 시 object 문자열 반환
console.log(typeof [], '<- array의 타입'); //array 타입 연산 시 object 문자열 반환
// 깊은 복사도 가능하지만 주의해야할 점 (배열과 객체도 마찬가지)
// 복사의 범위가 가장 바깥의 depth 까지다.
// const arr = [1,2,3,[5,6],4]; 의 경우 1,2,3,4는 깊은 복사를 하지만 5,6은 얕은 복사가 된다.

728x90
'Front - end > JS' 카테고리의 다른 글
| 23.04.09 / 배열, 객체, 함수, 생성자 함수가 헷갈린다... (0) | 2023.04.09 |
|---|---|
| 23.04.07 / 콜백(callback) & 클로저(closure) & 기타 함수 (0) | 2023.04.07 |
| 23.03.24 / 객체 타입, this, 매개변수와 인자 (0) | 2023.03.24 |
| 23.03.23 / 배열 (자바와 비교해서..) (0) | 2023.03.23 |
| 23.03.16 / 연산자 (종류와 우선순위) (0) | 2023.03.16 |