가비지컬렉터
참조 한개일 때
객체의 값을 다른 값으로 덮어주면 참조가 사라지면서 가비지컬렉터가 본래 값을 수집한다.
참조 두개일 때
참조 한개의 값이 덮어써지더라도, 한개는 여전히 가르키고 있으므로 가비지컬렉터는 수집해가지 않는다.
도달할 객체가 없을 때
서로 엮여있는 가족 객체가 있다.
John 객체에 연결된 참조를 삭제해보자
John 객체를 가르키고 있던 father과 husband 참조가 삭제되므로써
이제 John에 들어오는 객체는 없다. John에서 나가는 참조는 있지만,
이는 도달 불가능한 상황이므로 가비지 컬렉터에 의해 John이 수집된다.
근원(root) 객체에 null이 온다면
근원 (root) 자체가 null로 덮어써진다면, 그 아래에
가르키고 있던 모든 객체들은 도달할 수 없는 상태가 되므로 가비지 컬렉터에 의해 수집된다.
루트에서 도달하지 못하는 객체들은 모두 가비지 컬렉터가 수집하게 된다.
this와 메서드
메서드
user 객체에 function 메서드를 정의 ( 객체 안에 함수는 메서드라고 정의한다)
normal과 concise method 의 정의
normal method -> constructor 내장
concise method - > constructor 없음
this
uer.sayHi() 가 실행되는 동안 this는 user를 나타낸다. (객체를 호출한 대상을 가르킴)
this를 사용하지 않고 외부 변수(user.sayHi) 를 참조해 객체에 접근하는 것도 가능하다.
다만, user가 다른 값으로 덮어써졌을때를 생각해보면
이 때에는 user를 참조하여 직접 외부변수에 접근한 admin().sayHi가 문제를 일으킨다.
자유로운 this
this는 '점 앞의 객체'가 무엇인지에 따라 자유롭게 결정된다.
화살표함수 (this와의 바인딩 없다. )
실습1. 객체 내부의 menu 객체의 배열 요소 더하기
<1번째 방법>
forEach는 배열을 탐색하는 것이므로 먼저 배열에 접근해줘야 한다. => shopOrder.menu 까지 접근
shoOrder.menu.forEach() 를 돌려주면
이렇게 각각의 배열 하나하나를 탐색하게 될 것이다. (인자 명 : menu)
이의 price과 count에 접근이 필요하므로
menu.price / menu.count 를 통해 연산을 하고 출력한다.
<2번째 방법>
reduce를 이용해서 값을 누적해준다.
<객체의 프로퍼티로 메서드 정의>
객체의 프로퍼티로 해당 함수를 정의했다.
결과값은 this.total값에 저장해준다. 이를 위해서 객체에도 total:0 으로 초기값을 선언해준다.
예제2. 네비게이션
<오류상황>
ㄴ additem 은 this를 가지지 않기 때문에 새로운 객체가 전달되지 않는다.
따라서 arrowfunction을 normal function으로 변경한다.
프로토타입 상속
프로토타입 : 부모의 능력
자바스크립트의 모든 객체는 [[prototype]] 이라는 숨겨진 객체를 갖는다. 이는 NULL 또는 객체를 가르키고있다.
어떠한 객체를 참조하는 경우를 '프로토타입' 이라고 부른다.
프로토타입 동작방식
obect에서 프로퍼티를 읽으려고 하는데 없으면,
자동으로 프로토타입(부모의 능력) 에서 해당 프로퍼티를 찾는다.
프로토타입 강제 주입
rabbit에게 강제로 rabbit.__proto__ = animal 을 준다. (던더프로토)
이렇게 되면 rabbit도 부모의 프로퍼티인 eats를 갖는다.
객체 내부에 직접 던프로토를 작성해줌으로써 상속을 시킬 수 있다.
하단으로 계속해서 상속이 이어지는 이런 구조도 가능하다.
프로토타입은 '읽기전용' 이다.
프로토타입은 프로퍼티를 읽을 때만 사용한다.
수정하거나 지우는 연산은 객체에 직접 해야한다. (자식 객체에)
상속과 프로퍼티
부모의 메서드를 정의할 때 this를 사용했다면, -> 나의 메서드를 호출한 대상이 되는 것인데
부모가 가지고 있는 메서드라고 하더라도
자식의 rabbit이 __proto__를 상속받아, 해당 메서드(sleep) 을 사용한다고 했을 때
this.isSleeping = true; 의 this는 rabbit의 프로퍼티가 되어 사용될 수 있는 것이다.
- 자바스크립트에 모든 객체에는 숨긴 프로퍼티 [[prototype]] 이 있다.
- obj.__proto__ 를 사용하여 접근할 수 있다.
- 프로토타입에서 상속받은 method라도 obj.method()를 호출하면, this는 호출 대상인 객체를 가르키게 된다.
- for...in 을 사용하려면 hasOwnProperty를 call 해서 사용하는 방법이 보다 정확할 수 있다.
실습
setEat을 통해 과일을 넣으면
콘솔에 animal을 열거하면 grey가 생성된 것을 볼 수 있다.
getter와 setter을 정의하기
<getter와 setter 사용>
프로토타입 상속 방법 2가지
tiger에게 animal을 상속시켜준다.
tiger 객체 내부에서 상속을 주는 것도 가능하다.
다중 상속
맨 아래에 있는 백두산 호랑이 객체도 상위에 있는 메소드를 사용할 수 있다.
함수의 prototype 프로퍼티
*함수를 객체로 만들면 객체가 된다!
생성자 함수를 통해 만들어진 객체 a = '인스턴스'
생성자함수를 통해 만들어진 모든 인스턴스에는
던던프로토로 상속이 만들어진다.
생성자 함수를 만들고 (어차피 객체를 생성하는 기능을 하는 것.)
Rabbit.prototype = animal 이라는 프로퍼티로 상속을 설정해주고
ㄴ 이 때 기본으로 세팅되는 .prototype은 [[Prototype]] 과는 다르다. .prototype은 new Rabbit()을 호출할 때
만들어지는 새로운 객체의 [[Prototype]]을 설정하는 프로퍼티이다.
[[Prototype]]은 부모 객체인 animal이 되겠지 ~~???
ㄴ .prototype의 값은 null / 객체 만 가능하다.
ㄴ 일반 객체엔 .prototype을 추가해도 아무 반응이 없다! 오로지 '생성자 함수' 에만 생성됨!
객체를 공장처럼 찍어내는 것이다. -> new Rabbit('흰 토끼')
새로운 객체를 만든 후에 F.prototype을 바꾸게 되면?
기존에 만들어놓은 객체 : 기존의 상속을 따르게 된다.
이후에 만들어놓은 객체 : 새로운 상속을 따르게 된다.
생성자 함수를 만들면, 안에 내장하는 constructor가 있고
내장 constructor는 또 rabbit() 생성자함수를 가르키고 있다.
ㄴr의 constructor는 rabbit() 함수를 가르키고 있다.
ㄴ이 기능을 통해 다시 인스턴스를 만들어낼 수 있는 것이다. (이런 행동을 많이 하지는 않는다)
실습
ㄴ 현재 Tiger은 상단에 있는 Animal 생성자 함수와 전혀 관련이 없다. 이를 연결시켜 주려면?
방법1 ) Animal로 생성된 인스턴스 객체를 프로토타입과 연결시켜준다.
방법2 ) Animal을 빌려온다 (상속이라고 보기는 좀 어려움)
call -> 함수의 메서드 즉, 함수가 쓸 수 있는 능력이다. 대표적으로 (call, apply, bind)
call의 능력 : this를 대신 전달해준다.
마치 this는 age:11로 설정 된 것 처럼 설정해준다.
따라서
Animall 함수를 call이 실행하면서 this(한라산 호랑이) 인스턴스가 전달되는 것이다.
즉, 내가 생성한 인스턴스를 전달하는 것과 같다. = Animal 함수의 this 는 모두 '한라산호랑이' 가 된다.
한라산 호랑이객체가 모든 프로퍼티를 갖게되는 것이다!
+추가
call
call로 함수를 부를 때 매개변수는 이렇게 처리한다.
문자열로 넘어가는 첫 번째 매개변수 'a' 는 this를 뜻한다.
apply
apply로 함수를 부를 때 call과 거의 동일하나,
매개변수 전달 방식이 '배열' 임이 다르다!
bind
bind는 함수를 묶고, 바로 실행하지는 않는다. (call과apply는 바로 실행)
따라서, 별도로 실행을 시켜야 한다. => aa() 로 실행어 입력해야함
매개변수는 call과 같이 콤마로 전달을 해준다.
생성자 함수의 종류 2가지
prototype이 붙은 것 -> 상속된 애들만 쓸 수 있다.
static Method -> 누구나 다 쓸 수 있다.
<정리>
F 라는 생성자 함수가 있을 때, 이는 F.prototype을 통해서
만들고자하는 obj = new F()에 따라 생성된 obj의 __proto__를 설정할 수 있다.
따라서 F.prototype을 수정하면 영향을 받는 obj의 __proto__가 일괄적으로 수정된다.
다만, F.prototype 의 참조값이 변경되는 경우 (메모리상의 참조값)
변경되기 이전에 생성된 객체와 변경된 이후 생성된 객체의 prototype은 다르다.
클래스
클래스는 다음과 같은 기본 문법을 사용하여 만들 수 있다.
이렇게 클래스를 만든 뒤,
new MyClass() 를 호출하면 내부에서 정의한 메서드가 들어있는 객체가 생성된다!
(constructor는 자동으로 호출됨, 특별한 절차 없이 객체를 초기화할 수 있다. )
클래스의 형태
*메서드 사이엔 쉼표를 넣지 말자!
클래스의 특징
1. 클래스에 정의된 메서드는 열거할 수 없고, 프로퍼티에 추가된 메서드의 enumverable 플래그는false
2. 클래스는 항상 엄격모드로 실행된다. 클래스 생ㅅㅇ자 안 코드 전체엔 자동으로 엄격모드가 적용된다.
정적메서드
정적 메서드는 메서드를 프로퍼티 형태로 직접 할당하는 것과 동일하다.
User.staticMethod() 가 호출될 때, this의 값은 User그 자체 (점 앞 객체)
1. 정적 메서드는 어떤 특정한 객체가 아닌, 클래스에 속한 함수를 구현하고자 할 때 주로 사용됨
2. new "클래스이름" 으로 인스턴스 객체를 생성하지 않아도 해당 메소드를 사용할 수 있다는 장점이 있다.
<실습>
- getter, setter메서드는 User.prototype 에 쓰인다.
때문에 사실상 class Animal에 쓰인 get eat & set eat 은 User의 부모인 Object의 객체처럼 쓰이므로,
접근할 때 tiger.eat 으로 쓴다.
ㄴ tiger.eat / tiger.eat = '딸기' - static 메서드는 클래스에 직.접 접근해야 사용이 가능하다.
Tiger.bark()
이유는 static 메서드는 생성자 함수이기 때문에 인스턴스에서 직접 접근이 불가하다.
'JS' 카테고리의 다른 글
JS #10-자바스크립트 기초 개념10 (string, array 메서드) (1) | 2024.02.02 |
---|---|
JS #9-자바스크립트 기초 개념9 (클로저) (2) | 2024.02.01 |
JS #7-자바스크립트 기초 개념7 (객체) (1) | 2024.01.30 |
JS #6-자바스크립트 기초 개념6 (함수표현식, 화살표함수) (2) | 2024.01.30 |
JS #5-자바스크립트 기초 개념5 (반복문, 함수) (0) | 2024.01.25 |