-
자바스크립트 함수자바스크립트,제이쿼리 2019. 10. 6. 20:38
호출과 참조
자바스크립트에서는 함수도 객체이다. 따라서 다른 객체와 마찬가지로 넘기거나 할당할 수 있습니다.
함수 식별자 뒤에 괄호를 쓰면 자바스크립트는 함수를 호출하려 한다고 이해하고 함수 바디를 실행합니다. 그리고 함수를 호출한 표현식은 반환 값이 됩니다. 괄호를 쓰지 않으면 다른 값과 마찬가지로 함수를 참조하는 것이며, 그 함수는 실행되지 않습니다.
<script> function sayHello() { console.log("Hello world1"); console.log("Hello world2"); console.log("Hello world3"); } sayHello(); function getGreeting() { return "Hello world"; } console.log(getGreeting()); const arr = [1,2,3]; arr[0] = getGreeting; console.log(arr[0]()); </script>
값 뒤에 괄호를 붙이면 자바스크립트는 그 값을 함수로 간주하고 호출한다.
함수와 매개변수
함수를 호출하면 함수 매개변수는 변수 자체가 아니라 그 값을 전달받습니다.
function f(x) { console.log('x1= '+x); x=5; console.log('x2= '+x); } var x=3; console.log("호출 전 x=" + x); f(x); console.log("호출 후 x=" + x);
위 코드에서 중요한 것은 함수 안에서 x에 값을 할당하더라도 함수 바깥의 변수 x에는 아무 영향도 없다는 것이다.
이름은 같지만 둘은 다른 개체이다. 함수 안에서 매개변수에 값을 할당해도 함수 바깥에 있는 어떤 변수에도 아무런 영향이 없습니다. 하지만 함수 안에서 객체 자체를 변경하면, 그 객체는 함수 바깥에서도 바뀐 점이 반영됩니다.
function f(o) { o.message = "f에서 수정함"; o = { message : "새로운 객체!" }; console.log('f 내부: o.message=' + o.message); } var o = { message : "초기 값" }; console.log("f를 호출하기 전 : o.message=" + o.message); f(o); console.log("f를 호출한 다음 : o.message=" + o.message);
함수 내부의 매개변수 o와 함수 바깥의 변수 o가 서로 다르다는 겁니다.
f를 호출하면 둘은 같은 객체를 가리키지만, f 내부에서 o에 할당한 객체는 새로운, 전혀 다른 객체입니다.
함수 바깥의 o는 여전히 원래 겍체를 가리키고 있습니다.
객체의 프로퍼티인 함수
객체의 프로퍼티인 함수를 메서드라고 불러서 일반적인 함수와 구별합니다. 객체 리터럴에서도 메서드를 추가할 수 있습니다.
var o = { name : 'Wallace', bark : function() {return 'Woof!';} } console.log(o); console.log(o.name); console.log(o.bark());
this 키워드
this는 함수를 어떻게 선언했느냐가 아니라 어떻게 호출헀느냐에 따라 달라진다, 즉 this가 o에 묶인 이유는 speak가 o의 프로퍼티여서가 아니라, o에서 speak를 호출했기 때문입니다.
var o = { name : 'Wallace', speak() { return 'My name is ' + this.name + '!';}, } console.log(o.speak());
이와 같이 호출하면 자바스크립트는 아 험수가 어디에 속하는지 알 수 없으므로 this는 undefined에 묶입니다.
var speak = o.speak; console.log(speak === o.speak); console.log(speak());
var o = { name : "Julie", greetBackwards : function() { function getReverseName() { var nameBackwards = ""; for(var i=this.name.length-1; i>=0; i--) { nameBackwards += this.name[i]; } return nameBackwards; } return getReverseName + "si eman ym ,olleh"; }, }; o.greetBackwards(); var o = { name : "Julie", greetBackwards : function() { var self = this; function getReverseName() { var nameBackwards = ""; for(var i=this.name.length-1; i>=0; i--) { nameBackwards += self.name[i]; } return nameBackwards; } return getReverseName + "si eman ym ,olleh"; }, }; o.greetBackwards();
앞의 예제에서는 이름을 거꾸로 쓰고자 중첨된 함수 getReverseName를 사용했습니다. 하지만 getReverseName은 의도한 대로 동작하지 않습니다. o.greetBackwards()를 호출하는 시점에서 자바스크립트는 this를 의도한 대로 o에 연결하지만, greetBackwards 안에서 getReverseName을 호출하면
this는 o가 아닌 다른 것에 묶입니다. 이런 문제를 해결하기 위해 널리 사용하는 방법은 다른 변수에 this를 할당하는 겁니다.
함수 표현식과 익명 함수
익명 함수에는 함수에 식별자가 주어지지 않습니다.
함수 표현식은 함수 이름을 생략할 수 있다는 점을 제외하면 함수 선언과 문법적으로 완전히 같다.
var f = function() { // ... }
익명 함수는 어디든지 쓸 수 있다. 다른 함수나 메서드의 매개변수로 넘길 수도 있고, 객체의 함수 프로퍼티가 될 수도 있다.
함수 표현식에서는 함수 이름을 생략할 수 있는데 그렇다면 함수에 이름을 정하고 다시 변수에 할당하면 다음과 같아진다.
var g = function f() { //... }
이런 식으로 함수를 만들면 이름 g에 우선순위가 있다. 그리고 함수 바깥에서 함수에 접근할 떄는 g를 써야하며, f로 접근하려 하면 변수가 정의되지 않았다는 에러가 생긴다. 이런방법은 함수 안에서 자신을 호출할 때(재귀)에서 사용된다.
var g = function f(stop) { if(stop) console.log('f stopped'); f(true); }; g(false);
함수 안에서는 f를 써서 자기 자신을 참조하고, 함수 바깥에서는 g를 써서 함수를 호출한다.
나중에 호출할 생각으로 함수를 만든다면 함수 선언을 사용하면 되고, 다른 곳에 할당하거나 다른 함수에 넘길 목적으로 함수를 만든다면 함수 표현식을 사용하면 된다.
콜백함수
어떤 음식점이 당신이 줄을 서서 기다리지 않도록, 당신의 전화번호를 받아서 자리가 나면 전화를 해줍니다. 이런 음식점은 콜배고가 비슷하다. 자리가 나면 당신이 알 수 있도록 하는 수단을 당신이 음식점 주인에게 넘겨줍니다. 음식점은 다른 손님을 대접하면 되고, 당신은 다른 일을 하면 됩니다. 어느쪽도 서로를 기다리지 않습니다.
콜백은 간단히 말해 나중에 호출할 함수이다. 콜백 함수는 일반적으로 다른 함수에 넘기거나 객체의 프로퍼티로 사용한다.
console.log("Before timeout : " + new Date()); function f() { console.log("After timeout: " + new Date()); } setTimeout(f,60*1000); console.log("i happen after setTimeout!"); console.log("Me Too!"); setTimeout(function() { console.log("After timeout: " + new Date()); }, 60*1000);
출처 - 러닝 자바스크립트
'자바스크립트,제이쿼리' 카테고리의 다른 글
자바스크립트 콜백 (0) 2019.10.15 자바스크립트 스코프 (0) 2019.10.13 자바스크립트 객체 (0) 2019.10.07 자바스크립트 null과 undeifned (0) 2019.10.07 $.getJSON, $.ajax (0) 2019.06.27