배움 __IL/TIL 1기

TIL : 22번째- 221228 [12-5-수]

Mo_bi!e 2022. 12. 28. 19:28

I. 자바스크립트 : 함수

1. 함수?? 대입?? 객체??

 

JS는 함수를 정의 하는 일이 없다.

내가 쓰면서 정의를 한다.

 

int add(int x, int y){

   return x + y;

}

↑이거를

var add = new Function("x, y", "return x+ y");

함수객체로서 이렇게 할 수있다. (이 경우 new 'F'unction 으로 해야한다 )

함수객체 이름은 그냥 var add로 바로 된다.

 

add 호출 시

console.log(add(3,4))로 호출이 가능하다.

 

var add = new Function("x,y", "return x+y;");
     console.log(add(3,4));

JS는 정의한다고 하고 쓸 수있다

아래와 같이

var add =function(x,y){

 return x+y;

}

가능하다 (이 부분을 권장한다)

 

또다른방법도 있다

function add ( x, y ){...}   <== 이 부분은 비추

 

2. 이상하고 신기한... 자바스크립트 함수의 특징

(1) 함수객체를 생성하고 호출하기 1

function add(  x,  y){
  return x+y;
}
add(3,4,5,6); //

  하면은 어떻게 될까? 오류가 안난다.

 

다른 언어에서는 경험할 수없는 일임. 위험함... 실수로 값을 빼거나 더 넣어도 문제없다. (아파도 증상이 X : 무증상)

치명적으로 갑자기 즉사할수도....

 

매개변수는 의미없다. 받는역할은 다른 놈이 한다.

argumnets 컬렉션에 있다. 여기서 x,y는 큰 의미 없음

 

var add = new Function ("var x = arguments[0]"; "var y= arguments[1] ") 

 

function add(){
         return arguments[0] + arguments[1];
     }
     console.log(add(4,5));

이렇게 하더라도 9가 나온다.

 

결국 인수로 적더라도 더하면 결과값이 나올 수 있다.

function add2(  x,  y){

      return x+y+ arguments[2] + arguments[3];

    }
 console.log(add2(3,4,5,6));

18이 나온다.

(2) var 변수 선언과 위치

alert(a); //undefined
 var a= 1;

- undefined

선언한적이 없기 때문이 아니라, 선언한적이 있기 때문이다.

 

변수는 코드 실행시 먼저 스택에 잡힌다.

코드 전체 훑어 보면서 a가 올라가지만, 초기값은 아직 없다.

 

코드는 사용되기 전에 먼저 만들어진다.

 

(3) 변수를 선언하지 않고 사용하면?

스택에 잡히지도 않은 상태이다. 그런데 1이 나옴? 이 경우 스택에 없는 상태이다.

보이지않는 객체에 속성이 들어갔다. 전역객체라고한다.

alert(b); //not defined
b = 1;

b is not defined (아예 선언조차X)

undefined (선언만, 초기화는 X)와 다르다.

 alert(window.c); //undefined : 스택에 쌓여있는 경우 X
 window.c = 5;

한편 반대로 하면

window.d = 7;
alert(window.d)

7이 나온다. ( alert(d) 해도 동일함)

 

c = 1;
alert(window.c);

1 나옴

 

스택에 안올라갔지만, 전역객체가 받고있다.

이렇게 하면 된다.

사실상 c는  window.c 라고 볼수있다

(4) global 변수

var f1 = function(){
     d = 1; //함수안에서도 전역변수 사용이 가능핟.
     console.log(window.d);
 }

 f1();

window 붙였는지 여부 상관없이 1이 나옴

 

var f1 = function(){

      x = 1;
      var x;
      console.log(window.x); //undefined


  }
  f1();


    var f2 = function(){			  
      y = 1;

      console.log(window.y); //undefined

      var y;
  }
  f2();

애매하게 쓰는것은 바람직한 방법이 아님

 

 

(5) 동일변수를 여러번 선언하는 경우는?

var a = 1;

var a = 2;

 

Error <- 에러??안남  [나는것이 좋은거야 진단가능] 고로 꼼꼼해야한다.

그래서 ES6에서 수정 됨

 

 

(6) 중괄호를 사용하는 경우

코드 작성시에는 크게보다는 지역화가 바람직하다

{
  var a = 1;

}
alert(a);

이 경우 1이 출력된다. undefined 가아니다

즉 얘는 지역이 없다. (섬뜩...)

 

스크립트 100개파일 등으로 나눠서 작성할수도 있는데

모든 공간이 하나의 영역이다.

 

그래서 이거를 해결하고자 ES6가 나왔다.

 

(7) 함수 안에서 변수를 선언하는 것의 의미

선언 유무에 따라 전역인지 지역인지 나누어진다.

 

(8) 함수 안에서 선언한 global 변수 : stack에 쌓이는 것을 먼저 생각해보자!

함수 안 함수를 정의가 가능하다.

function f1(){
          var w = 10;
          f2();
          console.log("f1", w);

          function f2(){
              var w = 20;
              console.log("f2-1",w);
              f3()
              console.log("f2-2",w);

              function f3(){
                  w = 30;
                  console.log("f3",w);
              }
          }

      }
      f1();

이 경우 f3() 의 w 는 아웃터함수이다.

 

- var v2 에 대입한 경우 (위치조심)

function f1(){
      var w = 10;
      f2();

      /* 이 경우 f2만 만들어지고 함수는 존재하지 않음 
      그래서 위치를 f2()호출 보다 위로 올라가야한다.*/
      var f2 = function (){
          var w = 20;
          console.log("f2-1",w); //20
      }
      console.log("f1", w); //10
  }
  f1();

이 경우 f2만 만들어지고 함수는 존재하지 않음,

그래서 위치를 f2()호출 보다 위로 올라가야한다.

 

 

- <이 경우에는 뭘까?> : stack에 쌓이는 것을 먼저 생각해보자!

var f1 = function(){

  a = 1;
  console.log(window.a);
  console.log(a);
  var a;

}
f1();

변수를 선언하지 않았다는 것은 남의 것을 쓰는것이다

아우터가 있으면 아우터꺼 쓰고 없으면 전역을 쓴다.

 

-f3을 별도로 선언한 경우

var f3;
function f1(){
  var w = 10;

  /* 이 경우 f2만 만들어지고 함수는 존재하지 않음 
  그래서 위치를 f2()호출 보다 위로 올라가야한다.*/
  var f2 = function (){
      var w = 20;
    /*   console.log("f2-1",w); */
  }
  f2();

  f3 = f2;
  console.log("f1", w);


}
f1();

f3과 f2는 같다

 

 

- f1()을 두번 호출시 값은?

  function f1(){
      var w = 10;

      var f2 = function (){
          w++    
      }
      f2();

      console.log("f1", w);


  }
  f1();
  f1();

두번 다 11이다.

이것은 정상이다.

 

 

★ (9) 변수 생명주기와 클로저(closure : 문닫는 녀석) 

클로저란 내가 남을 닫게 할 수있는 키를 가지고있다 를 의미한다.
여기서 f2가 있음으로 의도적으로 변수가 지속적으로 살아남아 있게끔 하는 것이다. 

용도 : 클로저 발생하지 않도록 프로그램 만들거나
일부로 만들수도있다.

프토토타입을 이용해서 할수있는데 멤버메소드 일때 일부로 만든다.

사용하는게 당연 함

 

------------------------------

var f3;

function f1(){
      var w = 10;

      var f2 = function (){
          w++;
      }
      f2();

      f3 = f2; 
      console.log("f2", w);
}

  f1();
  f1();

이런경우 별게 없는거 같지만 메모리 누수가있다.

 

최초로 f3이 선언되면 그 선언된 주변에서 대입되는 등으로 쓰여져야한다.
하지만 이 경우 f3 f1함수 내에서 쓰여졌다.

결국 f3 선언 위치 때문에 메모리 누수가 발생한다.

 

function f1(){
      var w = 10;

      var f2 = function (){
          w++;
      }
      f2();

      console.log("f2", w);
}
var f3 =  f1();
f1();


f3을 쓸거면 f3함수 선언하고 바로로 대입하는 것이 바람직한것으로 볼수있다.

 

함수가 f3때문에  f2가 못죽고 f1 도 못죽는다. 즉 f1,f2가 스택에 사라지지않고있다.

 

f1() 두번째 호출시에 f1()만은 여전히 살아있다.

다른 것들은 다시 대입해서 이전것들은 사라지지만...

참조변수는 하나인데 새로운 객체가 다시 계속 만들어짐

 

1) 클로저란

클로저 문제는 함수가 물고있는 함수가 죽지못하고 살아있는게 문제다.

 

 

2) Closure in a Loop : 함수 객체 3개를 배열에 담아서 사용하는 코드

var funcs = [];

for(var i = 0 ; i < 3 ; i++)
      funcs[i] = function(){
      console.log(i);
  }

for (i in funcs){
  (funcs[i]());

}

이 경우 함수 배열은 아래와 같이 인덱스를 먼저 넣고 ()를 해준다.

아래 i에 다시 인덱스를 넣어서 i는 0부터 다시 시작됨

 

for(var i = 0 ; i < 3 ; i++)
          funcs[i] = function(){
          console.log(i);
      }


      funcs[0](); // log(i) 값은 여전히 i가 3으로 남아있는 중임
      funcs[1]();
      funcs[2]();

      for (i in funcs){ //i가  다시 0부터 시작 
          (funcs[i]());

      }

 

 

앞에있는 for문의 i가 뒤에도 영향을 준다.

  for(var a = 0 ; a < 3 ; a++){
		  funcs[a](); }

이 경우 a로 하면 i에 새로이 선언해서 하는것이 아니기 때문에 여전히 i가 3으로 영향을 미친다.

 

그 이유는 a값은 인덱스만 영향미치지 본 함수 안에있는 console.log(i); 에서 

i값이 3이라는것은 여전히 유효하다.

 

 

 

II. 자바스크립트  인스턴스 관리하기 : OOP

언어가 지원하지 않지만, 객체 지향스럽게 만들고 싶어든

1. 객체 생성과 삭제

js모든 객체는 속성을가지고 있고, 확장할수있다.

// ar.papa();

var name =new String("newlec");
name.kor = 20;
console.log(name.kor);

(1)  객체를 삭제하는 방법

exam = null;

객체 자체가 다 없어 진다.

 

(2) 객체 속성 제거

delete exam.kor;
delete exam.kor;

속성 제거됨

 

(3) JS 기본 객체 사용법

var ar = [5];
ar.Mo = function(){
    console.log(ar);
}
ar.Mo();


이런방식으로 새롭게 만들어서 사용할수도 있다

 

 

★(4) JS 클래스의 Expand 기능 지원하지 않는다. 

var name = new String("newlec");
name.kor = 20;
console.log(name.kor);     //에러가 발생

이 기능은 ES6에서는 된다.
그러나 ES5에서는 new String은 함수가 아니기 때문에 함수의 속성으로서 하지못한다. 
즉 String는 expand 확장하지 못한다

2. 객체 사용법

(1) new 의 의미

function Exam(){
    kor = 30;
}

함수 선

 

1) new가 없는 경우

var exam1 = Exam();
// 이것은 함수를 호출하기만 하는 것이고 return이 없어서 받을 수는 없다.

console.log(exam1);
// console.log(exam1.kor); //에러

이 경우 new 가없으면 새로운 객체가 만들어 진것이 아니고,
함수의 리턴값을 변수 exam1에 넣어야한다
그러나 이 경우에 exam1에는 대입 될 것이 없다

 

특히 .kor로 접근한 경우에는 에러가 뜬다 ★
왜냐하면 new 가없어서 받은 것이 없기 떄문이다.

 

2) new 사용

var exam2 = new Exam(); 

console.log(exam2);
console.log(exam2.kor);

new 를 이용해서 새로운 객체를 만든다.
함수는 이 객체를 먹었고, 함수는 이 객체를 함수 내에서 사용할 수 있다. 결국 속성을 추가해줄 수 있다.
이 경우 데이터를 초기화 하기 위해서 함수명은 대문자로 사용한다.

 

 

(2) this 의미 

function Exam(){
    this.kor = 30;
    console.log(window.kor); 
    console.log(this.kor); //그냥 하면 오류 뜸 꼭 this 써야함
    //window 하면은 new 함수 호출 시 new에 따라서 다르게 볼 수 있음
}

window.kor
에서 window나 this를 붙이지 않으면 오류가 뜬다
우선 this 로 선언했으면 this로 해야한다.
window는 모르겠다 ★

 

new Exam();
Exam();
//둘다 호출이 되고 30이 나온다
//this 는 자기가 사용할 수이는 기본객체이다.
//this 는 window가 될수도 있긴하다.

위 아래 차이는 위는 객체를 만들어서 한다.
이 경우 함수를 호출하면 this공간에서 작용할 수있게 된다.

new 없이 하게 되면 전역객체로서 작용하게 된다.
그래도 객체라서 this도 window도 모두 가능하다.

 

(3) 자바스크립도 자기만의 객체 생성 가능(this + new 이용)

function Exam(){
        this.kor = 30;
        this.eng = 20;
        this.math = 40;

        this.total = function(){
            return this.kor + this.eng + this.math;
        }
    }

    var exam = new Exam();
    console.log(exam.total());

    var exam1 = new Exam();
    console.log(exam1.total());

약간 객체지향스럽지만 은닉성보장은 어려움

new 를 이용해서 자신만의 객체를 만들 수 있다.

즉 new를 할 때 마다 새로운객체가 다시 만들어진다

 


1. 보충

1) 클로저 개념 + 메모리 누수 쟁점

 

 

2) new 와 this 에 대한 이해인데,
이러한 경우 JS특유의 객체 내용 이해 못함 ㅜㅜ

 

2. 회고 

1) JS의 객체내용과 java와의 내용이 충돌된다.
이 지점에서 계속해서 이해를 하는데 걸림돌이 된다.