JavaScript/Javascript_Advanced

[JS]Function(함수) part.4

MoZZANG 2022. 4. 12. 22:11
 /*
  자스는 프로토타입 기반의 언어로 프로토타입(원형)을 만들고 속성이나 함수를 
  객체에 추가한다
  자스에서 객체를 만드는 법 두 가지
  
  1. 중괄호 사용(Literal 객체-JSON(JavaScript Object Notation)) 
      
      var 객체명 = {}; 혹은 {"속성":"값",....}
      속성 추가시에는 객체명.속성명=값;
      함수 추가시에는 객체명.함수명 =function(){};

  2. 생성자 함수 사용       
      function 생성자함수명(){
        this를 사용해서 속성 설정             
      }
      -보통 일반함수와 구분하기위해 함수명을 대문자로 시작
      -return문을 안쓴다
      -생성자 함수에는 주로 속성만 정의한다
      var 객체명= new 생성자함수명();
      -함수는 객체명.prototype.함수명=function(){}로 별도로 정의한다.
      
  ※상속
    자식의 생성자 함수 안에서 
    부모생성자함수.apply(this, arguments);
    부모자 생성자의 this와 arguments(매개변수)를 적용한다는 의미
    
    메소드는
    자식생성자함수.prototype = Object.create(부모생성자함수.prototype);
    Object의 create()함수로 부모의 프로토타입으로 자식의 프로타입을
    생성한다는 의미.이러면 부모의 메소드를 상속받게 된다
    
    자식생성자함수.prototype.constructor = 자식생성자함수;//생략시 자식의 생성자 함수가 부모가 된다 즉 반드시 있어야 한다
  */

 

 

하나씩 예제를 직접보면서 이해해보자.

 

 

//[첫번째.{}로 객체 만들기]
    var brace = {};//new Object();와 같다.Object()이 생성자 함수 
    console.log('타입:%s,brace:%O', typeof brace, brace);
    for (key in brace) console.log('키:%s,값:%s', key, brace[key]);
    //Object.keys(객체) : 키값을 배열로 반환
    var keys = Object.keys(brace);
    console.log(keys);
    //Object.values(객체) : 값들을 배열로 반환
    var values = Object.values(brace);
    console.log(values);
    //속성 추가
    brace.username = '가길동';
    brace.years = 20;

▲ brace라는 객체를 하나만들고 for~in문을 이용해서 brace객체안의 속성과 값을 꺼내와 보았다. 당연히 빈객체이므로 []로 출력이 될 것이며 Object타입은  var 변수명 = {}로 만들던지 var 변수명 = new Object() 처럼 생성자 함수로 객체를 만들던지 모두 타입은 Object이다. 

 

중괄호를 사용해서 객체를 만드는 것을 리터럴이라고 하고 리터럴로 객체를 만들면 속성 및 함수 추가시에는 객체명. 으로 접근한다.

 

brace라는 객체에 속성이 username에 값이 가길동을, years라는 속성과 그 값으로 20을 추가해주었다.

 

 

 

//함수 추가

    brace.print = function () {
      console.log(this);//window객체가 아니라 brace객체 자신
      console.log(this === window);//false
      console.log('이름:%s,나이:%s', this.username, this.years);
    };
    brace.makeFriend = function (username, years) {
      console.log('%s의 친구 이름은 %s이고 그 친구의 나이는 %s살이다', this.username, username, years);
    };

▲ 위에서 brace라는 객체에 print속성에 값으로 함수를,  makeFriend라는 속성에 갑승로 함수를 추가하였다.  이는 new생성자가 아닌 리터럴 방식으로 객체를 만들었기 때문에 객체명. 으로 만들 수 있었던 것이다.

 

위 print 함수안에서 this는 window를 가리키는게 아닌 brace를 가리킨다. 왜냐하면 print라는 함수를 호출하고 있는 것은 window객체에서 호출하는 것이 아닌 brace객체에서 호출하고 있기 때문이다.

 

makeFriend()함수내에서의 this또한 역시  같은 이유로 brace를 가리킨다.

 

 keys = Object.keys(brace);
    console.log(keys);
    values = Object.values(brace);
    console.log(values);

▲ Object객체의 keys()함수와 values()함수는 객체의 모든 키값을 가져와서 값들을 배열로 반환한다.

 

 

 

//속성 값 읽기 : 객체명.키 혹은 객체["키"]
//단,키를 변수처리시에는 반드시 객체[변수명]로 접근해야 한다
    console.log(brace.username);
    console.log(brace['years']);

 

 

//함수 호출
    brace.print();
    brace.makeFriend('가길순', 25);

 

 


 

 //JSON.stringify(JOSN객체):JSON형태의 문자열로 변환-함수는 제외됨
    var jsonString = JSON.stringify(brace);
    console.log(jsonString);//"{키:값.,...}" 형태의 문자열
    console.log(typeof jsonString);

JS의 객체들을 나중에 백엔드와 같은곳에 전송할 때는 문자열로 변환하여 전송해야한다. 백엔드에서는 JS의 객체를 알지 못하기 때문이다. 이렇게 문자열로 변환하여 전송하면 백엔드에서는 다시 parsing하여 객체를 속성과 값으로 분리해서 인식하게 된다.

 

JS에서 객체를 문자열로 변환할 때는 JSON이 가지고 있는 stringify()함수를 사용하여 변환할 수 있다.

 

출력시 마치 객체처럼 보이지만 타입을 찍어보면 string 타입인것을 볼 수 있다. 또한 stringify할 때 키값들은 초기에 single quotation으로 감싸져있던 quotation으로 감싸져있지 않든 모두 double quotation으로 감싸지게 되는 것을 볼 수 있다.

 

주의할사항은 stringify를 할 때는 함수는 제외되고 문자열화 된다는 것이다.

 

//JSON.parse(JSON형태의 문자열) : 문자열을 자바스크립트 객체로 변환.
//JSON.parse()적용시 키는 반드시 ""으로 감싸야 정상적으로 파싱된다
    var jsonObject = JSON.parse(jsonString);
    console.log(jsonObject);
    console.log(typeof jsonObject);

 

▲ 우리가 백엔드 쪽에서 JSON형태의 문자열로 어떠한 data를 받았을 때 이를 JS의 객체로 변환해야 속성과 값으로 구분해서 인식할 수 있다. 이럴 때는 JSON의 parse()함수를 사용하면 된다.

 

▲문자열이 객체로 바뀐것을 볼 수 있다.

 

 

 

 

//{}brace로 객체 생성시 처음부터 속성 및 함수 설정]
//키값은 ' 나 "로 감싸지 않아도 된다(자스코드에서).
//단,값은 받드시 감싸야 한다(숫자는 예외)
    var brace2 = {
      num1: 10, 'num2': '20', "num3": '삼십',
      add: function () {
        return this.num1 + parseInt(this.num2);
      },
      minus: function () {
        return this.num1 - this.num2;
      }
    };
    console.log(brace2.num1);
    console.log(brace2["num2"]);
    console.log(brace2.add());
    console.log(brace2.minus());

▲ 숫자형식의 문자열과 숫자를 더하기 연산할 때는 숫자가 문자열로 바뀌어서 문자열끼리 결합한 연산이 되어버리므로 this.num2를 숫자타입으로 바꾸기 위해서 parseInt()를 사용해 주었다. 

 

 

 

 //속성 두개 추가
    brace2.num4 = 40;
    brace2['num5'] = 50;
    console.log(JSON.stringify(brace2));//키가 ""감싸져 있지 않더라도 문자열로 변환시 ""감싸진다

 

 

 //객체의 속성 삭제 :  delete 객체명.속성명 혹은 delete 객체명['속성명']
    delete brace2.num4;
    delete brace2['num5'];
    delete (brace2.minus);
    console.log(brace2);

 

 

 

 

 

//[두번째. 생성자 함수로 객체 만들기]
//생성자함수로 객체를 만들면 같은 구조의 객체를 계속해서 
//찍어 낼수 있다.({}로 객체를 만들때는 불가)
    function Human(username, years) {
      //Human객체 속성 추가
      this.username = username;
      this.years = years;
      this.birthDate = new Date();//디폴트값으로 설정
      console.log(this);
    }

 

 

-- 함수 추가하기

 

//함수 추가하기 
 //생성자함수.prototype.함수명=function(){}; 자바의 인스턴스형 메소드와 같다
    Human.prototype.print = function () {
      console.log('이름:%s,나이:%s,생일:%s', this.username, this.years, this.birthDate);
    };

▲ 생성자함수로 객체를 만들었을 경우 함수를 추가할 때는 두가지 방법이 있다. prototype을 사용하거나 사용하지 않거나. prototype을 사용해서 함수를 추가하면  마치 자바의 인스턴스형 메소드와 같아서 호출하려면 new 생성자함수를 사용하여 인스턴스화를 해주어야 한다.

 

 

//클래스 함수:자바의 정적 메소드와 같다.
//-this키워드는 클래스 함수에서 사용하지 않는다
//-생성자함수.함수명=function(){}
//-생성자함수.함수명으로 호출
    Human.inform = function (legs, arms) {
      console.log(this.username);//undefined
      console.log('인류는 포유류다.다리는 %s개 팔은 %s개이다', legs, arms);
    };

▲ 위처럼 prototype을 사용하지 않고 함수를 추가하면 마치 자바의 정적메소드와 같이 생성자함수. 함수명으로 접근할 수 있다. 위와같은 함수를 클래스 함수라고 한다.

 

//클래스메소드 호출
    console.log('Human.inform() 호출');
    Human.inform(2, 2);

 

 

//Human을 일반 함수처럼 호출시 - this는 Window객체
//Human('가길동',20);
//Human을 new로 객체화시 - this는 객체화 된 Human객체를 의미
//new 생성자함수()
    var human = new Human('가길동', 20); //인스턴스화
    console.log(typeof human);
    console.log(human);

 

 

 

//함수 호출
    human.print();

 

 

 //속성의 값 바꾸기
    var human_ = new Human('나길동', 30);
    human_.print();
    human_.years = 35;
    human_.print();

 


상속

 

//instanceof연산자:해당 객체가 어떤 생성자 함수 타입인지 알아내는 연산자.
//변수(객체명) instanceof 생성자함수명

//JS의 모든 객체는 Object로부터 상속 받았다
var array = new Array(10);
console.log(array instanceof Array);//true
console.log(array instanceof Object);//true
console.log(array instanceof String);//false

 

 

1. 부모의 모슨 속성 상속받기

//자바스크립트에서의 객체 상속하기
//Human을 상속 받자

//1.부모의 모든 속성 상속 받기
function Asian(username, years, race) {

  //부모 생성자의 this와 arguments(매개변수)를 적용한다는 의미.
  //자바의 super(username,year)와 같다.    
  Human.apply(this, arguments);//this는 Human
  //자식에서 race속성 추가
  this.race = race;
  }

 

 

2. 부모의 메소드 상속받기

//2.부모의 메소드 상속 받기
Asian.prototype = Object.create(Human.prototype);
//아래 생략시 Asian.prototype.constructor===Human 이 true
//즉 Asian의 생성자 함수는 Human이라는 의미
Asian.prototype.constructor = Asian;//Asian의 생성자함수는 Asian이 된다.

//Asian에 새로운 함수 추가
Asian.prototype.farm = function () {
 console.log('%s살인 %s가 농사를 짓다', this.years, this.username);
};

 

 

- 새롭게 생성자함수로 인스턴스화

var asian = new Asian('다길동', 25, '황인종');
    console.log(asian);
    console.log(asian instanceof Asian);//true
    console.log(asian instanceof Human);//true

▲ asian은 Asian 즉 자기자신 타입이므로 true, asian은 Human을 상속받았으므로 true 

 

 

console.log(Asian.prototype.constructor === Human);//false
console.log(Asian.prototype.constructor === Asian);//true

▲ 위에서 Asian.prototype.constructor = Asian;을 해주었으므로 Asian의 constructor는 Asian 즉 자기자신이 된다.

 

 

 

asian.farm();//새롭게 자식에서 추가한 메소드
asian.print();//상속받은 메소드(오버라이딩 전)

 

 

- JS의 오버라이딩

//오버라이딩:상속받은 부모의 함수를 재정의. 
//          오버라이딩이라는 개념은 존재하나 단,매개변수와 반환값이 일치하지 않아도 된다(함수명은 동일하게)
Asian.prototype.print = function (language) {
   console.log('이름:%s,나이:%s,생일:%s,인종:%s,언어:%s',
   this.username, this.years, this.birthDate, this.race, language);
 };
 asian.print('한국어');//상속받은 메소드(오버라이딩 후)

 

 

console.log('Object의 toString()오버라이딩 전');
console.log(asian.toString());

 

 

 //toString() 오버라이딩
 Asian.prototype.toString = function () {
     return this.username;
   };
console.log('Object의 toString()오버라이딩 후');
console.log(asian.toString());

▲ 오버라이딩이 되어 Asian의 username만 출력되었다.

 

 

 

 

 

'JavaScript > Javascript_Advanced' 카테고리의 다른 글

[JS]DOM(Document Object Model) part.2  (0) 2022.04.14
[JS]DOM(Document Object Model) part.1  (0) 2022.04.13
[JS]Function(함수) part.3  (0) 2022.04.12
[JS]Function(함수) part.2  (0) 2022.04.12
[JS]Function(함수) part.1  (0) 2022.04.12