생성자, 객체, This

김종현·2023년 1월 15일
0

Js

목록 보기
2/16

객체; Object

-이름과 값으로 이루어진 속성들을 포함하는 container.
-일종의 디렉토리(파일관계) - 연관된 변수와 함수의 집합; 원하는 변수와 함수를 쉽게 찾을 수 있으며 서로 다른 의미(쓰임)를 가지는 변수와 함수가 한곳에 모여있을 때 일어나는 간섭현상을 줄이거나 해소 가능.

배열과의 차이점

-데이터 추가시 배열 전체에서 중복되지 않는 인덱스가 자동으로 만들어져 추가된 데이터에 대한 식별자가 된다.
-아이템에 대한 식별자로 숫자를 사용하며, 인덱스로 문자를 사용하고 싶다면 객체(dictionary)를 사용해야한다.

객체의 구성

-객체 내의 변수 = 속성; property
-객체 내의 함수 = 메소드; method
*다른 언어에서는 연관배열(associative array), 맵(map), 딕셔너리(Dictionary)라는 데이터 타입이 객체에 해당한다.

객체의 형태

-key : value의 관계이다.
-중괄호를 사용하며 한 쌍의 이름과 값은 ','로 구분되고 ':'로 분리된다.
-객체명.[key] = value; 에서 ]key는 따옴표 생략가능, 작은/큰 따옴표 사용가능], value는 문자일 경우 작은/큰 따옴표 사용.

const hero = {name : 'Garen'};

-기본형

const hero = {
  name : 'Garen',
  skills : ['QQ', 'W', 'E', 'R'],
  attack : 60,
  defence : 30;
  }

-응용형
-위의 문자열, 숫자, 배열 두개;데이터 아이템을 객체의 property라고 부른다.
-함수를 Method라고 한다.

객체의 생성

-★변수를 정의하고 초기화하면서 시작.

① 객체 리터럴 표기법 이용.
-데이터 값 그 자체 즉, 변수에 넣는 변하지 않는 데이터(리터럴)식 객체 표기법.
-중괄호 내에 콤마로 구분하며 세미콜론 붙이지 않음.

let hero = {
	'name' : ["Garen", 'Galio'],
    "skills" : 'QQ',
    attack : 60,
    defence : 30
    }
console.log(hero.name)		>> Garen
console.log(hero.skills)	>> QQ

② new Object를 이용
-Object 입력시 첫글자 대문자에 유의.
-동적으로 프로퍼티와 메서드를 추가해줄 수 있다.
-new Object(); = {};

let hero = new Object();
	hero['name'] = ['Garen', 'Galio'],
	hero["skills"] = 'QQ',
	hero['attack'] = 60,
	hero['defence'] = 30;
//혹은 
let hero = new Object();
	hero.name = ['Garen', 'Galio'];
    hero.skills = 'QQ';
    hero.attack = 60;
    hero.defence = 30;

-key를 나타내는 대괄호 내 따옴표 생략불가.
각 키 = 밸류 구분시 ' , ' 사용 가능, 마지막에 ' ; ' 으로 마감.
각 키 = 밸류 구분시 각각 ' ; '으로 마감.

객체의 값을 가져오는 방법

-프로퍼티 이름, 배열의 일부, 객체의 메소드 호출 가능.

-①점 표기법 : 객체 이름은 namespaces처럼 작동한다. 객체내의 아이템에 접근하려면 점을 찍고 접근하고자 하는 항목을 적는다. 상수 값만을 사용.

-②대괄호 사용 : 멤버의 값을 동적으로 변경할 수 있을 뿐아니라, 멤버 이름까지도 동적으로 사용, 홑 따옴표 사용.

hero.skills

hero['skills']
hero['ski'+'lls']

객체값의 설정(갱신)

①value 변경

hero.name = 'Teemo'
console.log(hero.name);		>> 'Teemo'
// Garen, Galio가 사라지고 Teemo만 남음

②새로운 key와 value 추가 (멤버추가)
-대괄호 표현의 이점 중 하나는 멤버의 값을 동적으로 변경할 수 있을 뿐아니라, 멤버 이름까지도 동적으로 사용할 수 있다는 점이다.

hero['name']['troll'] = 'Nami';
console.log(hero.name)		>>	'Garen', 'Galio', troll: 'Nami'
alert(hero.name); 			>> Garen,Galio
alert(hero.name.troll);		>> Nami

-troll이라는 키 값에 Nami라는 밸류를 부여하여 name에 추가.
-Hero.name.troll = 'Nami'; 로도 가능함.

hero['items'] = 'Doran Sword';
console.log(hero['items'])	>> 'Doran Sword'
//함수도 추가 가능하다.
hero.pick = function() {alert("pick your champ");}
console.pick();				>> pick your champ

③두 개의 텍스트 입력을 통해서 Hero 데이터에 커스텀 값을 넣고 싶다면

var myDataName = nameInput.value;
var myDataValue = nameValue.value;

-위를 활용하면 된다.

var MyDataName = 'position';
var myDataValue = 'top';
hero[MyDataName] = myDataValue;

console.log(hero.position)	>> top

-점 표기법으로는 위처럼 멤버의 이름을 동적으로 사용할 수 없고 상수 값만을 사용해야 한다.

생성자와 new

서론

-Js류는 prototype-based programming 이므로 객체 지향의 문법을 비슷하게 사용하는 함수 언어이다. 즉, 객체 이전에 함수!
-객체지향 프로그래밍 목적 : 객체를 통해 좋은 부품의 logic을 만드는 것.

생성자(constructor) 함수

-객체를 만드는 함수. Js에서 함수는 재사용 가능한 로직의 묶음이 아니라 객체를 만드는 창조자이기도 하다.

생성자의 특징

-일반적인 객체지향 언어에서 생성자는 class 내에 속한다. 즉, class를 통해 생성자를 부여한다. 하지만 Js에서 객체를 만드는 주체는 함수다.
-생성자는 일반함수와 구분하기 위해 보통 첫글자를 대문자로 표기한다.
-★생성자는 객체를 만들고 객체에 대한 초기화(init : initializing)를 한다.

  • 객체 내에 어떤 프로퍼티/메서드를 가질지 생성자 함수 내에 기술함으로써 그 객체가 가진 기능성을 세팅해준다.

-var p = new Person(); => 함수를 호출할 때 new를 붙이면 해당함수는 생성자가 되어 비어있는 새 객체를 만들고 그 객체를 반환한다(객체를 변수 p에 담는다).

-즉, 함수에 new를 붙이면 그 리턴값은 객체가 된다. 따라서 p = Person{}. let p = {}라고도 할 수 있다.(완전히 같진 않음)

-이때 변수 p에 담긴 new Person()은 빈 객체이므로 p.name = 'egoing', p.introduce = function(){}와 같이 데이터를 부여해주면된다.


-만약 여러 사람을 위한 객체를 만든다면 위와 같이 코드를 작성해야 하는데 이 경우 프로퍼티 name과 메소드 introduce가 중복되므로 개선이 필요하다.


-생성자 내에서 이 객체의 프로퍼티를 정의하고 있다.

  • this.name
  • this.introduce = function(){...}
    -이러한 작업을 초기화(객체에 대한 초기화)라고 하며 이를 통해서 코드의 재사용성이 대폭 높아졌다.
  • 위의 코드에서 p1, p2에 각각 introduce 함수를 지정할 필요 없이 객체에 메서드를 정의하였으므로 꺼내서 쓰기만 하면 되기 때문이다.
    -즉, 생성자가 만든 빈 객체가 어떠한 프로퍼티와 메소드를 가져야하는지 생성자 함수 안에 기술함으로써 그 객체가 가지고 있는 정보와 로직을 세팅(초기화, init : initialize)하여 코드를 개선하였다.

This

-★함수 내에서 this는 그 함수가 소속되어있는 객체를 가리킨다.

-함수 내에서 함수 호출 맥락(conetext)을 의미한다. 즉 함수를 어떻게 호출하느냐에 따라서 가리키는 대상이 달라지며 언제나 정확한 값을 사용하게 해준다.

-함수와 객체의 관계가 느슨한 Js에서 this는 둘 사이의 연결점 역할을 한다.

-객체 리터럴을 직접 지정해서 사용하는 경우는 효용성이 떨어지나 동적으로 객체를 생성하는 경우, 특히 생성자를 사용하는 경우에는 매우 유용하다.

(1)
this는 무엇이든 될 수 있다.

function test() {
    console.log(this);
}

//test(this = 10, )
test.call(''); => [String: '']
test.call('hello'); => [String: 'hello']
test.call({ a: true }); => {a:true}
test.call(11); => [Number : 11]

function sum(a,b){
console.log (a+b+this);
}
sum(1,2); => 3
sum.call(null, 1, 2) => 3
null 자리에 this가 들어갈 수 있음.

function sum(a,b){
console.log (a+b+this.offset);
}
sum.call({offset:30}, 1, 2); =>33

-

const another = () => {
    console.log(this);
    //const a a= `test: ${this}`; 일 경우 ?
};
화살표 함수에서는 this를 마음대로 바꾸지 못하게 제한시킴. -> 선언하는 순간 변경 불가.
another.call('hello');  =>  함수에서 [String: 'hello'], 화살표 함수에서 {}
another.call(true);  =>  함수에서 [Boolean: true], 화살표 함수에서 {}

(2) 함수에 붙여쓰는 bind, call, apply

//call, bind, apply는 this를 줘야하는 함수

function sum(...nums) {
//(...nums) nums에 해당하는 애들을 모아서 배열로 반환 => [1, 2, 3, 4]
    console.log(nums);  => [1,2,3,4]

    return nums.reduce((a, b) => a + b, 0);  =>10
}

console.log(sum(1,2,3,4)); => 
console.log(sum.call(null,1,2,3,4));

//일단 null값은 무시하고 보기. this 들어가는 부분. 지금 쓸일 없음.
const add10 = sum.bind(null, 10); => sum(10, 0)같음 => [10]
const add20 = add10.bind(null, 20); => sum(10, 20)같음 => [10, 20]
const add100 = add20.bind(null, 100); => sum(10, 20, 100)같음 => [10, 20, 100]
//sum에 변수를 묶어두기만함. 연속적으로 붙여서 쓸 수 있음.

console.log(add100()); => 110

console.log(add100.call(null, 3));
// ?

console.log(add100.apply(null, [3, 4, 5]));
console.log(add100.call(null, ...[3, 4, 5]));

함수호출

-함수를 호출했을 때 this는 전역 객체인 window와 같다.

-결과 값 : window === this

메소드의 호출

-객체의 소속인 메소드의 this는 그 객체를 가리킨다.

-결과 값 : o === this

정리

-기본적으로 어떠한 전역 변수/객체(어떤 메소드에 속해있지 않은 객체)의 경우에는 window에 속해있다.
-따라서 func();라는 함수는 실질적으로 window라는 객체의 메소드이다. 즉, 표기되지 않았으나 전역 객체인 window에 속해있다.
-이 말은 func();와 o.func();의 this가 가리키는 것은 달라도 실질적으로 둘 모두 객체에 이미 속해있으므로 각각 this가 window와 o를 가리킨다.

생성자 내에서의 this; 생성자의 호출

-★함수 안에서 this는 그 함수가 소속되어있는 객체를 가리킨다.
-★생성자 내에서 this는 그 생성자가 만든 객체를 가리킨다.

①o1 : func();의 호출에 따라 this는 funcThis에 할당이 되고, funcThis는 함수 내에서 변수 할당이 안 되어 있으므로 전역 변수를 받아오는데 null;이므로 this가 세팅이 된다. 함수를 호출시 함수는 window라는 객체의 메소드이므로 즉, 이 '함수' 내에서 this = window.
따라서 this = funcThis = window

② o2 : func();에 의해 this = funcThis, o2는 생성자에 의해 객체가 된다. 즉, '객체' o2 내에서 this = o2.
따라서 this = funcThis = o2

function Func(){
	if(o2 == this){
	}
}

var o2 = new Func();
	if(funcThis === o2){
    	document.write('o2 </br>');
    } 									>>undefined.

-생성자 호출시 생성자에 대한 호출이 모두 완료된 후에야 변수(o2)에 생성한 객체 할당이 이루어진다. 그 전까지 객체는 만들어져 있지만 실제로 변수(o2)에 할당이 되어 있지 않으므로 객체를 참조할 수 없으므로 undefined이다.
-존재하지 않는 것(o2)과 this를 비교한 것이기 때문에 문제가 생긴다.
-★생성자 내에서 this는 객체가 초기화가 끝난 뒤 어떤 식별자에 담기기 전에 그 객체를 참고할 수 있게 해주는 식별자이다.

참조 :
-https://developer.mozilla.org/ko/docs/Learn/JavaScript/Objects/Basics ; 객체
-https://opentutorials.org/module/532/6571 ; 생성자, this

profile
나는 나의 섬이다.

0개의 댓글