본문 바로가기
📙 자바스크립트 공부

자바스크립트 this에 대해 다시 복습, 상속과 class 개념 정리!!!

by 따따시 2022. 12. 16.

 

function user(first, last) {
  this.firstName = first;
  this.lastName = last;
}

user.prototype.getFullName = function () {
  return `${this.firstName} ${this.lastName}`;
};
// 이렇게 new를 사용한 함수를 '생성자 함수' 라고 한다.
// 하나의 객체 데이터가 생성되는 것
// a,b,c => 인스턴스
const a = new user("f1", "l1");
const b = new user("f2", "l2");
const c = new user("f3", "l3");

console.log("a : ", a.getFullName());
console.log("b : ", b);
console.log("c : ", c);

>> 프로토타입

const a = [1,2,3] 이라고 만들고

콘솔창에 a를 출력해보면,

__proto_가 있는데, 이 프로토를 열어보면

아래처럼 메소드들이 다 있음!!!!!


>> this 는 ?

  1. 일반 함수는 ‘호출 위치’에 따라 this를 정의
  2. 화살표 함수는 자신이 선언된 ‘함수 범위’에서 this를 정의

case 1)

// // >> 프로토타입
// // 이 prototype을 우리는 알게모르게 계속 쓰고 있었음

// const whatProto = [1,2,3];
// console.log('whatProto',whatProto)
// // 이거 브라우저 콘솔창에 찍어보셈 , proto나옴

// // 생성자 함수일때는 첫번째 단어를 '대문자'로 써주는 것이 관행
// // User라고 되어있는것만 보고도 new랑 같이쓰는 생성자함수라는걸 알아차릴수있음
// function User(first, last) {
//     this.firstName = first;
//     this.lastName = last;
//   }

//   user.prototype.getFullName = function () {
//     return `${this.firstName} ${this.lastName}`;
//   };

//   const a = new user("f1", "l1");
//   const b = new user("f2", "l2");
//   const c = new user("f3", "l3");

//   console.log("a : ", a.getFullName());
//   console.log("b : ", b);
//   console.log("c : ", c);

// >> this
// 1. 일반 함수는 '호출 위치'에 따라 this 정의
// 2. 화살표 함수는 자신이 선언된 '함수 범위'에서 this를 정의

const thisFun = {
  name: "hong",
  normal: function () {
    console.log("normal의 this :", this.name);
  },
  arrow: () => {
    console.log("arrow의 this :", this.name);
  },
};

// 일반함수는 자기가 호출되는 위치에서 this가 정의된다.
// 일반함수가 그냥 선언되어 있을때는 아직 this가 정해지지 않은 상태임
// 이 normal함수는 thisFun 안에서 실행이 되는데, 44번 라인에서 '호출'이 될 때
// 자기의 앞에있는 thisFun가 this로 맵핑되는 것
thisFun.normal();
// 화살표 함수는??
// 자신이 '선언'된 '함수' 범위에서 this가 정해지는데, (37번 라인) this가 없으니 undefined가 출력
thisFun.arrow();

const detailFun = {
  name: "detailName",
  normal: thisFun.normal,
  arrow: thisFun.arrow,
};

// 여기서 thisFun.normal은 괄호()로 '실행'이 되고 있는게 아니라
// 단순히 '할당'이 되는 것

// 일반함수 : 자기가 '호출'될 때 앞에 detailFun가 있으니 detailFun의 name이 출력되고
detailFun.normal();
// 화살표 함수 : 화살표 함수는 자기가 '선언'된 곳 37번라인에서 this를 찾는데 여전히 모르니 undefined 출력
detailFun.arrow();

case 2)

function User(name) {
  this.name = name;
}

User.prototype.normal = function () {
  console.log("nomal의 this.name:", this.name);
};
User.prototype.arrow = () => {
  console.log("arrow의 this.name:", this.name);
};

const test = new User("testName");

// 일반함수는 자기가 호출되는 때에 this가 정해지니
// testName이 될 것 같고
test.normal();
// 화살표함수는 자기가 선언된 곳에서니 아무것도 할당되지 않을 것 같음
test.arrow();

  1. 콜백함수로 일반함수를 선언했을때
const timer = {
    name: "timer !!!",
    tiemeout: function () {
      // setTimeout(함수, 시간)
      setTimeout(function () {
        console.log(this.name);
      }, 2000);
    },
  };

timer.tiemeout();

콘솔창 결과 찍어보면 this.name이 undefined가 나온다

—> 이유 ?

this.name이 들어있는 일반함수가 선언된 곳은 setTimeout이기 때문!!

—> 그렇다면?

화살표 함수로 바꿔주면, 화살표함수는 자신이 선언된 곳의 범위로 this를 인식하니, (아래 참고)

  1. 화살표 함수로 바꿔줬을때
const timer = {
  name: "timer !!!",
  tiemeout: function () {
    // setTimeout(함수, 시간)
    setTimeout(() => {
      console.log(this.name);
    }, 2000);
  },
};

timer.tiemeout();

저 ( ) ⇒ { } 가 속해있는 더 큰

function ( ) { } 을 범위로 인식하고, 이 function은 자기가 호출되는 곳에서 this가 결정되니

자기가 호출되는 곳은 즉, timer.timeout();에서 timer이니 this가 timer의 name이 되는 것

(자세하게 풀어쓰기)

❣️ 뽀인트

따라서, setTimeout이나 setInterval을 사용할 땐

() ⇒ { } 화살표 함수를 콜백함수로 사용하면 되게찡!!!!


예제)

const thisFun = {
  name: "hong",
  normal: function () {
    console.log("normal의 this :", this.name);
  },
  arrow: () => {
    console.log("arrow의 this :", this.name);
  },
};

여기서 주목!!!

normal: function () {
    console.log("normal의 this :", this.name);
  },

이 부분에서 < : function > 을 지워도 똑같음 (아래처럼 됌)

normal () {
    console.log("normal의 this :", this.name);
  },


ES6 문법

class User {
  constructor(x, y) {
    this.firstName = x;
    this.lastName = y;
  }
}

class 를 적어주고 constructor를 사용했는데 저 constructor는 아래와 같은 의미이다.

constructor : function () { }
// 이게 : function이 생략되서, 
// constructor  ( ) { } 이 된거라고 보면 됌

+) 기존에 프로트타입을 사용하여 메소드를 추가했는데, 이렇게 class를 사용하면

class User {
  constructor(x, y) {
    this.firstName = x;
    this.lastName = y;
  }
//  바로 이렇게 프로토타입을 사용하지 않고, 프로토타입으로 만든 메소드를 이런식으로 넣어줄 수 있음 
  getFullName(){
    return `${firstName} ${lastName}`
  }
}

구버전) 프로토타입 이용해서 User에 메소드 추가했던 것

User.prototype.getFullName = function () {
  return `${this.firstName} ${this.lastName}`;
};

상속(확장)

const myBicycle = new myBicycle ( '자전거' , '바퀴2개' );
// 이렇게 넘기면
// myBicycle의 constructor 안에 ( '자전거' , '바퀴2개' )가 전달이 되고 
// 전달된 name,wheel은 super(=Vehicle) 안으로 전달이 되는 것
class User {
  constructor(x, y) {
    this.firstName = x;
    this.lastName = y;
  }
//  바로 이렇게 프로토타입을 사용하지 않고, 프로토타입으로 만든 메소드를 이런식으로 넣어줄 수 있음 
  getFullName(){
    return `${firstName} ${lastName}`
  }
}

구버전) 프로토타입 이용해서 User에 메소드 추가했던 것

User.prototype.getFullName = function () {
  return `${this.firstName} ${this.lastName}`;
};

상속(확장)

const myBicycle = new myBicycle ( '자전거' , '바퀴2개' );
// 이렇게 넘기면
// myBicycle의 constructor 안에 ( '자전거' , '바퀴2개' )가 전달이 되고 
// 전달된 name,wheel은 super(=Vehicle) 안으로 전달이 되는 것

댓글