2024/04/01 메서드와 this, 생성자 함수(new연산자)

YIS·2024년 4월 1일
post-thumbnail

메서드 : 객체 내에서 특정한 행동을 할 수 있도록 함수를 프로퍼티로 할당하는 것.

메서드 만들기

let user = {
  name: "John",
  age: 30,
  //   sayHi: function(){
  //   return "안녕하세요!"
  // }                    //객채 리터럴방식 직접추가
  
};
// function sayHi() {
//   return "안녕하세요!"
// }
// user.sayHi = sayHi;    //만들어진 함수를 추가해서 할당

user.sayHi = function() {
  return "안녕하세요!";
};						  //함수선언하면서 메서드 할당

console.log(user.sayHi()); //안녕하세요!

메서드 단축 구문

let user = {
  name: "John",
  age: 30,
  sayHi: function(){
  return "안녕하세요!"
  }   
}                       
//일반 함수표현식

let user = {
  name: "John",
  age: 30,
  sayHi () {
    return "안녕하세요!"
  }
}
//단축 구문

console.log(user.sayHi()); //안녕하세요! 

두 방법은 완전히 동일하진 않음.
단축 구문을 사용한 메서드 정의는 super 키워드를 사용할 수 있는 능력을 포함하는 반면,
일반 함수 표현식으로 정의된 메서드는 그렇지 않음.
객체의 메서드가 상속과 관련된 기능이 필요할 때 중요해 질 수 있으나 지금은 넘어감




메서드와 this

객체의 메서드 내에서 this 키워드를 사용하는 것은
메서드가 속한 객체에 저장된 정보에 접근하기 위한 일반적이고 중요한 방법임.
this는 메서드가 호출될 때 메서드를 호출한 객체를 가리킴.
이를 통해 메서드는 객체의 다른 프로퍼티나 메서드에 접근할 수 있게 됨.

let user = {
  name: "John",
  age: 30,
  sayHi() {
    console.log(this.name); // 'this'는 '현재 객체'를 나타냅니다.
  }
};
user.sayHi(); // John

user.sayHi() 메서드가 호출될 때, this는 user 객체를 가리키게 됨.
this.name은 user 객체의 name 프로퍼티에 접근하는 것과 같음.
따라서 메서드는 동적으로 현재 객체에 접근할 수 있으며, 코드의 유연성과 재사용성이 향상됨.
this.name이 아닌 외부변수 user을 직접 가져다 user.name를 써도 가능함.
하지만 밑의 예시를 보자.

let user = {
  name: "John",
  age: 30,
  sayHi() {
    console.log( user.name ); // Error: Cannot read property 'name' of null
  }
};
let admin = user;
user = null; // user를 null로 덮어씁니다.
admin.sayHi(); // sayHi()가 엉뚱한 객체를 참고하면서 에러가 발생.

user 객체를 다른 변수에 할당한 후 user 변수를 수정하거나 다른 값으로 덮어쓰면,
원래의 user 객체를 참조하던 메서드는 더 이상 유효한 참조를 가지지 않게됨.
이는 메서드가 예상치 못한 값을 참조하거나,
존재하지 않는 프로퍼티에 접근하려고 할 때 에러를 발생시킴.

위의 예시에서 user 객체를 null로 덮어쓴 후 admin.sayHi()를 호출하면,
sayHi 메서드 내부에서 user.name을 참조하려고 함.
그러나 이 시점에서 user는 null이므로, null.name에 접근하려고 하여 에러가 발생.

헷갈리면 안되는게 let admin = user; 선언으로 admin과 user은 동일한 객채를 가리킴
user = null;로 user은 null값이 덮어씌워지지만,
admin변수는 여전히 이전에 참조하던 객채를 가리키고있음.

그래서, this를 사용했다면 this는 메서드를 호출한 admin 객체를 가리키므로,
this.name은 여전히 유효한 참조를 통해 admin 객체의 name 프로퍼티에 접근할 수 있음.




자유로운 this

자바스크립트에서 this는 모든 함수에서 사용할 수 있으며,
함수가 호출될 때 해당 함수가 속한 현재 객체를 참조함.
동일한 함수라도 다른 객체에서 호출되면 this가 참조하는 값이 달라짐.
즉, 함수가 호출될 때 this는 그 함수가 속해 있는 현재 객체(점(.) 앞의 객체)를 가리키게 됨.

let user = { name: "John" };
let admin = { name: "Admin" };

function sayHi() {
  console.log( this.name );
}//sayHi함수선언. 호출될 때 this 객체의 name 프로퍼티를 콘솔에 출력.
user.temp = sayHi;
admin.temp = sayHi;
//앞서 정의한 sayHi 함수를 각각user,admin 객체의 temp 프로퍼티로 할당. 
user.temp(); // John  user객체의 temp프로퍼티를 호출, sayHi내의 this는 user 객체를 참조
admin.temp(); // Admin user객체의 temp프로퍼티를 호출, sayHi내의 this는 admin 객체를 참조
admin['temp'](); // Admin (대괄호 표기법. 특정상황에서 씀(유효하지않은이름,동적이름))

자바스크립트 this는 항상 메서드가 정의된 객체를 참조하는게 아님.
메서드가 어디서 정의되었는지에 상관없이 this는 ‘점 앞의’ 객체가 무엇인가에 따라 ‘자유롭게’ 결정됨.
(그래서 너무 어려움.이해가 잘 안됨.)




this가 없는 화살표 함수(이해안됨)

화살표 함수는 일반 함수와 달리 자신만의 this를 가지지 않음.
대신, 화살표 함수 내에서 this를 사용하면,
그 this는 화살표 함수를 둘러싼 가장 가까운 일반 함수 또는 전역 스코프의 this를 참조하게 됨.
이 특성 때문에 화살표 함수는 특정 컨텍스트 내에서 this를
"고정"시키는 용도로 매우 유용하게 사용.

객체의 메서드 내에서 화살표 함수를 사용하는 경우,
화살표 함수 내의 this는 해당 메서드의 this와 같은 값을 가지게 됨.
이는 메서드가 속한 객체를 가리키게 됨.

let user = {
  firstName: "보라",
  sayHi() {
    let arrow = () => console.log(this.firstName);
    arrow();
  }
};
user.sayHi(); // 보라

sayHi는 일반 함수로서 user 객체의 메서드.
따라서, sayHi 내에서의 this는 user 객체를 가리킴.
sayHi 내부에서 정의된 arrow는 화살표 함수.
화살표 함수는 자신이 생성될 당시의 this를 "캡처"함.
여기서 arrow가 생성될 때의 this는 sayHi의 this, 즉 user 객체.
그 결과, arrow 내부에서 this.firstName을 호출하면,
user.firstName을 가리키게 되고, "보라"가 출력

화살표 함수의 특징 중 하나는 바로 this가 화살표 함수가 생성될 때의 컨텍스트(즉, 주변 환경)를 "기억한다"는 점임. 여기서 sayHi 메서드 내부에서 화살표 함수를 정의했기 때문에, 화살표 함수의 this는 sayHi 메서드가 호출될 때의 this와 같음.

일반함수의 this는 그 함수가 호출되는 방식에 따라 결정됨.
객체의 메서드로서 함수가 호출될 때, this는 그 메서드를 호출한 객체를 가리킴.

화살표 함수는 자신만의 this를 생성하지 않음.
대신, 화살표 함수는 그 함수가 정의된 스코프의 this를 "상속"받음.
이 말은, 화살표 함수 내에서 사용된 this는 화살표 함수를 둘러싸고 있는
가장 가까운 일반 함수의 this를 참조한다는 의미.
만약 그런 일반 함수가 없다면, 전역 스코프의 this를 참조하게 됨.
화살표 함수가 어디서 호출되든지 간에, 그 this 값은 변경되지 않음.
이는 화살표 함수가 처음 생성될 때의 this를 "기억"하기 때문.
(쓰고도 이해가 100%안됨)




생성자 함수

객체를 생성하기 위해 사용되는 특별한 함수.
객체의 초기 상태를 설정하고, 객체가 생성될 때 필요한 초기화 작업을 수행.
"new"연산자를 붙여 실행
생성자 함수를 사용하면, 코드의 재사용성을 높이고, 객체의 생성 과정을 표준화 할 수있음.


기본문법
function 생성자함수이름(파라미터1, 파라미터2, ...) { this.속성1 = 파라미터1; this.속성2 = 파라미터2; ... }

  • 생성자함수이름: 일반적으로 생성자 함수 첫글자는 대문자. 이는 생성자 함수임을 나타내는 관례.
  • 파라미터: 생성자 함수가 받을 입력 값. 이를 통해 객체의 초기 상태를 설정할 수 있음.
  • this: 생성될 객체 자신을 가리키는 키워드.
    생성자 함수 내에서 this를 사용하여 객체의 속성이나 메소드를 정의할 수 있음.
function Person(name, age) {
  this.name1 = name;
  this.age1 = age;
  this.introduce = function() {
    console.log(`안녕하세요, 제 이름은 ${this.name1}이고, 나이는 ${this.age1}살입니다.`);
  };
}

let person1 = new Person('홍길동', 30);
person1.introduce(); // 출력: 안녕하세요, 제 이름은 홍길동이고, 나이는 30살입니다.
let person2 = new Person('심청이', 15);
person2.introduce(); // 출력: 안녕하세요, 제 이름은 심청이이고, 나이는 15살입니다.

new 키워드를 사용하여 생성자 함수를 호출하면, 해당 함수에 의해 새로운 빈 객체가 생성.
이때 this는 새로 생성된 빈 객체를 가리키게 됨.
속성과 메서드로 name1,age1,introduce가 할당되고 추가됨.

밑에 예시처럼
재사용할 필요가 없는 복잡한 객체를 만드는 경우 new function(){}을 활용해
익명 생성자 함수를 사용하기도 함.

let user = new function() {
  this.name = "John";
  this.isAdmin = false;
  // 여기에 더 많은 코드들...
};
console.log(user.name); // 출력: John

익명 생성자 함수는 특정 상황에서 단 한 번만 사용되는 복잡한 객체를 생성할 때 유용함.




profile
엉덩이가 무거운 사람

0개의 댓글