🐟 함수
인수
, 함수의 출력 값 : 반환값
, 함수 정의문의 인수 : 인자(parameter)
🐟 함수 hoisting
// ex) console.log(square(5)); // 25 function square(x) { return x * x ; }; // 정상 동작
🐟 값으로서의 함수
함수 선언문
(function "함수이름" (인자) { }; )으로 함수를 선언할때, 내부적으로 그 함수 이름을 변수 값으로 한 변수와 함수 객체가 생성참조
가 저장// ex) let sq = square; console.log(sq(5)); // 25
🐟 참조
에 의한 호출 vs 값
에 의한 호출
원시 값(primitive value)
을 인수로 넘길때와, 객체
를 인수로 넘길때 다르게 동작 ✨🐙 원시값이 인수일 경우
// ex) function add(x) { return x = x+1; } let a = 3; let b = add(a); console.log("a = " + a + ", b = " + b ); // a = 3, b = 4
👉 함수가 호출될 때 변수 a의 복사본이 인자 x에 할당 ➡ 값 자체가 인자에 전달 (
값의 전달
)
👉 변수 a와 x는 다른 영역의 메모리에 위치한 별개의 변수
🐙 인수가 객체일 경우
// ex) function add(p) { p.x = p.x + 1; p.y = p.y + 1; return p; } let a = { x:3, y:4 }; let b = add(a); console.log(a, b); // Object {x=4, y=5} Object {x=4, y=5}
👉 함수 호출시 변수 a의 복사본이 인자 p에 할당
👉 이전과 다른건 변수 a 에 객체의 참조가 저장되어 있으며, 이 참조 값을 인자 p에 대입하는것. ➡ 인수를 객체로 넘길 때 전달 되는 값은 참조값 (참조 전달
)
👉 인자 p와 변수 a는 똑같은 객체를 참조
👉 함수 안에서 p.x와 p.y를 수정하는 행위는 a.x와 a.y를 수정하는 행위와 같음 ➡ 함수 안에서 원래의 객체 변경 가능❗ 함수에 넘겨야 하는 인수 개수가 많아질때의 문제
1) 인수의 순서를 착각할 수 있음
2) 함수가 받는 인수 개수를 바꿀때 함수의 호출 방법이 바뀌므로 프로그램 전체를 수정해야함//ex) function setBallProperties(x, y, vx, vy, radius) { ... } setBallProperties(0, 0, 10, 15, 5);
❗ 이를 해결하기 위해서는?
➡ 인수를 객체 프로퍼티에 담는다var parameters = { x: 0, y: 0, vx: 10, vy: 15, radius: 5 }
❗ 함수의 인수를 하나만 받도록 변경 가능
function setBallProperties(params) { ... } setBallProperties(parameters);
👉 함수 안에서 프로퍼티를 읽는 코드는 params.vx 등으로 표현 가능하므로 인수 순서를 고려하지 않아도 됨
👉 인수 추가시에도 프로퍼티만 추가하면 되므로 함수 호출 방식은 동일함을 유지할 수 있음var parameters = { x: 0, y: 0, vx: 10, vy: 15, radius: 5, color: "blue" } setBallProperties(parameters);
❗ 주의사항: 함수 안에서 객체의 프로퍼티를 수정할 경우, 객체의 참조가 전달된 상태 이므로, 호출한 코드에 있는 인수 객체의 프로퍼티가 함께 바뀜
🐟 변수
유효범위
🐠 전역 유효 범위
와 지역 유효 범위
'전역 변수'
와 '지역 변수'
로 구분🐠 변수의 충돌
// ex) let a = "global"; function f() { var a = "local"; console.log(a); // local return a; } f(); console.log(a); // global
🐠 함수 안에서의 변수 선언
과 변수 끌어올림
// ex) function f() { console.log(a); // undefined let a = "local"; console.log(a); // local return a; }
🐠 함수 안에서의 변수 선언 생략
// ex) function f() { a = "local"; console.log(a); // local return a; } f(); console.log(a); // local // 언뜻 a는 함수 f의 지역 변수처럼 보이지만, var로 선언하지 않았으므로 실제로는 전역 변수
🐟 블록 유효 범위 : let
과 const
블록 유효 범위
를 갖는 변수를 선언🐸 let 선언자
let x;
let a, b, c;
let x = 5, y = 7; // ex) let으로 선언한 변수의 유효 범위 let x = "outer x"; { let x = "inner x"; let y = "inner y"; console.log(x); // inner x console.log(y); // inner y } console.log(x); // outer x console.log(y); // ReferenceError : y is not defined // 중괄호 바깥의 변수 x의 유효범위 : 전체 프로그램 // 안에 있는 변수 x의 유효 범위 : 중괄호 안쪽 // y의 유효 범위는 중괄호 안이므로 y를 함수 밖에서 읽으려고 시도하면 참조오류 발생
ex) console.log(x); // ReferenceError: x is not defined let x = 5;
// ex) let x; let x; // Uncaught SyntaxError
🐸 const 선언자
// ex) const c = 2; c = 5; // Uncaught TypeError
// ex) const origin = { x:1, y:2 }; origin.x = 3; console.log(origin); // Object { x:3, y:2}
🐟 함수 리터럴로 함수 정의하기
함수 표현문
)ex) let square = function(x) { return x * x; };
ex) console.log(square(3)); // TypeError : square is not a function let square = function(x) { return x * x };
// ex) let square = function sq(x) { return x * x }; // 코드에서 sq라는 이름은 함수 안에서만 유효하므로, 함수 바깥에서는 sq라는 이름으로 함수 호출이 불가 // 익명 함수 코드는 모두 anonymous function이라고 표시되므로 함수를 구별할 수 없으나, // 이름이 붙은 익명 함수는 어떤 함수인지 확인은 가능
🐟 객체의 메서드
함수 객체의 참조를 값으로 담고 있는 프로퍼티
ex) var circle = { // 원의 중점 표현 객체 center : { x:1.0, y:2.0 }, // 원의 반지름 radius : 2.5, // 원의 넓이를 구하는 메서드 area: function () { return Math.PI * this.radius * this.radius; } } circle.area() // 19.634954084936208
// ex) circle.translate = function(a, b) { this.center.x = this.center.x + a; this.center.y = this.center.y + b; }; circle.translate(1, 2); circle.center; // Object {x=2, y=4}
🚀 함수를 활용하면 얻을 수 있는 장점
[1] 재사용 가능
[2] 만든 프로그램을 이해하기 쉬움
[3] 프로그램 수정이 간단