JavaScript function 탐구 - 이름있는 함수 / 함수 선언식

FGPRJS·2021년 10월 20일
0

function의 이름있는 함수 / 함수 선언식을 탐구한다.


이름있는 함수 / 함수 선언식

  • 다음을 이름있는Named 함수라고 한다.
    해당 함수는 i_am_named_function 이라는 이름이 있다.
function i_am_named_function(){
    console.log("i'm named!");
}
i_am_named_function(); //i'm named!

  • JavaScript의 변수는 오로지 참조만을 하고, 엄격한 타입제한등이 있지 않아 이름있는 함수는 다음과 같은 기이한 동작도 가능하다.
function i_am_named_function(){
    console.log("i'm named!");
}

//변수에 다른 변수를 참조시켜버린다.
i_am_named_function = "actually, i'm not function"

//i_am_named_function(); //오류가 난다!
//TypeError: i_am_named_function is not a function

console.log(i_am_named_function);
//actually, i'm not function

  • 이름있는 함수는 다음과 같이 사용할 수 있다.
let GreetingFactory = {
    hi: say_hi,
    hello: say_hello,
    bye: say_bye
}

function say_hi(){
    console.log("hi!");
}

function say_hello(){
    console.log("hello!");
}

function say_bye(){
    console.log("bye!");
}

GreetingFactory.hello(); //hello!
GreetingFactory.bye(); //bye!
GreetingFactory.hi(); //hi!

  • 변수가 함수를 참조하고 있기 때문에, 변수를 참조해서 콜백함수로 쓸 수 있다. 물론 여기서 참조되는것은 변수 그 자체가 아니라 변수가 참조하는 함수이다
function doubling(value){
    return 2 * value;
}

//map 함수는 collections의 각 member를 대상으로 함수를 수행한다.
console.log([1,2,3,4,5].map(doubling));
// [2,4,6,8,10]


function adder(bfval, curval){
    return bfval + curval;
}

/* reduce 함수는 collections들의 지정한 index부터 (없으면 0)
 * 지정한 초기값으로부터(없으면 0) 해당 함수를 수행하고 
 * 그 결과를 다음 수행에 반영한다.
 * 그 후 최종 값을 반환한다.
 */
console.log([1,2,3,4,5].reduce(adder));
// 15

  • 함수 선언식은 함수 선언 전에 사용할수 있다.
hoi();

function hoi(){
    console.log("hoi");
}
  • 무명함수 / 함수 표현식을 사용한 예시.
    다음 코드의 주석을 제거하면, 오류가 발생한다.
    • var로 선언한 helloworld는 hoisting을 통하여 선언 과정에서 존재한다는 것은 인지하였으나 실행 과정에서 순차적으로 보았을 때 아무것도 참조하지 못하여 아직 무엇인지 모른다(undefined).
console.log(helloworld);
//undefined

//helloworld();
//TypeError: helloworld is not a function

var helloworld = function(){
    console.log("hello world!");
}

이름있는 함수에서의 this 사용

  • this실행과정에서 호출될 때 결정(바인딩)되는 키워드이다.
function say_hello(){
    console.log("hello!", this.target);
}

const GreetingFactory = {
    target: "GF",
    hello:say_hello
  //hello는 say_hello함수를 참조한다.
}

GreetingFactory.hello(); // hello! GF
  • 해당 코드를 다음과 같이 이해할 수 있다.
    • say_hello함수참조하고 있다.
    • GreetingFactoryhellosay_hello가 참조하고 있는 함수를 참조한다.
      (say_hello를 참조하는 것이 아니다.)

  • 따라서, 다음 코드와 결과는 동일하다고 볼 수 있다.
function say_hello(){
    console.log("hello!", this.target);
}

const GreetingFactory = {
    target: "GF",
  //hello는 say_hello의 함수를 참조하는것이 아니라, 
  //익명 함수를 참조한다.
    hello:function(){
        console.log("hello!", this.target);
    }
}

GreetingFactory.hello(); // hello! GF
  • 다음을 통해 상기 강조한 표현을 증명할 수 있다.
function say_hello(){
    console.log("hello!", this.target);
}

const GreetingFactory = {
    target: "GF",
    hello:function(){
        console.log("hello!", this.target);
    }
}

const GreetingFactoryCopycat = {
    target: "GFCopy",
  //이렇게 GreetingFactory의 hello를 가져오더라도,
  //진짜 GreetingFactory의 hello를 가져오는게 아니라
  //GreetingFactory의 hello가 참조하고 있는 함수만 참조한다.
    hello:GreetingFactory.hello
}

GreetingFactory.hello(); //hello! GF
GreetingFactoryCopycat.hello(); //hello! GFCopy
  • GreetingFactoryhello를 호출하기 때문에, 이것을 this로 봄을 알 수 있다.

  • 다음과 같은 IIFE 방식으로 즉시 실행할수도 있다. IIFE 특성으로 해당 함수에 의한 Side-Effect가 존재하지 않는다.

(function myfunction() {
    console.log("hello world!");
})(); // hello world!
//myfunction();
//ReferenceError: myfunction is not defined
profile
FGPRJS

0개의 댓글