[JavaScript] 생성자 함수

김방울·2022년 10월 3일
0

JavaScript

목록 보기
3/6

자바스크립트 객체 생성 방식

  1. Object() 생성자 함수 사용
    자바스트립트는 객체를 생성할 수 있는 내장 생성자 함수 Object()를 제공한다.
//Object()를 이용해서 빈 cat 객체 생성
const cat = new Object();

//cat 객체 프로퍼티 생성
cat.name='방울';
cat.age='4';
cat.gender='female';

console.log(typeof cat); //object
console.log(cat); // {name: '방울', age: '4', gender: 'female'}
  1. 객체 리터럴 이용 방식
    객체 리터럴은 중괄호({})를 이용해서 객체를 생성한다. {} 안에 아무것도 적지 않으면 빈 객체를 생성한다. 중괄호 안에 ‘프로퍼티 이름' : ‘프로퍼티 값’ 형태로 표기하여 해당 프로퍼티가 추가된 객체를 생성할 수 있다. 이 때 프로퍼티 값이 함수인 경우, 이를 메소드라고 한다.
const cat  = {
    name : '방울',
    age : 4,
    gender : 'female',
    says : function(){
     console.log('야옹')   
    }
}
  1. 생성자 함수 이용
    자바스크립트의 생성자 함수는 타 객체지향 언어와는 다르게 생성자 함수의 형식이 정해져 있는 것이 아니라, 기존 함수에 new 연산자를 붙여서 호출하면 해당 함수가 생성자 함수로 동작하게 된다.
    특정 함수가 생성자 함수인 것을 알리기 위해 함수 이름의 첫 문자를 대문자로 쓰는 것이 관례이다.
// Cat() 생성자 함수
const Cat = function (name) {
    this.name = name;
}

// bangul 객체 생성
const bangul = new Cat('방울');

console.log(bangul.name);
// 방울

객체 리터럴 방식 vs 생성자 함수 방식

객체 리터럴 방식으로 생성된 객체는 같은 형태의 객체를 재생성할 수 없다.
이에 반해 생성자 함수를 사용하여 객체를 생성하면, 생성자 함수를 호출할 때 다른 인자를 넘김으로써 같은 형태의 서로 다른 객체 bar와 baz를 생성할 수 있다.

// 객체 리터럴 방식으로 foo객체 생성
var foo = {
	name: 'foo',
	age: 35,
	gender: 'man'
}
console.dir(foo);

// 생성자 함수
function Person(name, age, gender, position) {
	this.name = name;
	this.age = age;
	this.gender = gender;
	this.position = position;
}

// Person 생성자 함수를 이용해 bar 객체, baz 객체 생성
var bar = new Person('bar', 33, 'woman')
console.dir(bar)
var baz = new Person('baz', 25, 'woman')
console.dir(baz)

Prototype

function Champion(){
	this.q = 'strike';
	this.w = 'snowball';
}

const nunu = new Champion();

상속 기능을 구현하는 장치. 자식에게 어떤 형질을 물려줄지 결정하는 유전자와 비슷하다.

nunu는 item 속성을 직접 가지고 있지 않지만 item 속성을 사용할 수 있다.

Array 자료형에 기본적으로 사용할 수 있는 .sort() 등의 메서드가 있다. Array 내의 원소만 추가해 주었고 .sort()를 추가한 적 없는데 .sort()를 사용 가능한 이유가 무엇일까?

Array() 의 prototype(유전자) 에 .sort(), .length 등이 정의되어있기 때문이다.

Array.prototype.함수 = function(){}

prototype을 활용하면 모든 Array type에 사용이 가능한 함수를 만들 수 있다.

Class

ES6의 클래스가 도입되기 이전에는 생성자 함수로 프로토타입 기반의 인스턴스를 생성하였다. 클래스와 생성자 함수는 모두 프로토타입 기반의 인스턴스를 생성하지만 정확히 동일한 동작을 하지는 않는다.

  • costructor

클래스의 몸체에서는 constructor 가 생성자 역할을 한다. 인스턴스를 생성, 초기화 하는 특수한 메서드이므로 이름 변경이 불가능하다. 아래와 같은 코드로 클래스를 만들고 인스턴스를 생성하는 것이 가능하다.
constructor는 클래스 내에 최대 1개만 존재 가능하다.

	class Cat {
// 생성자 역할을 합니다.
	constructor(name){
	// 인스턴스 생성 및 초기화 진행이 가능합니다.
	this.name = name;
	}
	meow(){console.log(this.name + ': 야옹')}
}
// 클래스를 호출하여 인스턴스를 만들었습니다.
const myCat = new Cat('bangul');

!

Cat() 이라는 이름을 가진 함수를 만든다. 함수 본문은 생성자 메서드 constructor 에서 가져온다. 생성자 메서드가 없으면 본문이 비워진 채로 함수가 만들어진다.
meow() 와 같이 클래스 내에서 정의한 메서드를 Cat.prototype에 저장한다.

  • prototype method

만약 프로토타입으로 메서드를 만들어주지 않는 경우에는 인스턴스가 생성될 때마다 계속해서 메서드를 생성해 주어야 한다. 클래스는 보다 더 간결하게 프로토타입 메서드를 생성하는 것이 가능하다.

class Cat {
// 생성자 역할을 합니다.
	constructor(name){
	// 인스턴스 생성 및 초기화 진행이 가능합니다.
	this.name = name;
	}
// 프로토타입 메서드
	meow(){console.log(this.name + ': 야옹')}
}

//클래스를 호출해서 인스턴스를 만들었습니다.
const myCat = new Cat('bangul');

//프로토타입 메서드를 호출했습니다.
myCat.meow() // bangul: 야옹

인스턴스는 프로토타입 메서드를 상속받아 사용하는 것이 가능하다. 즉 클래스도 결국은 생성자 함수와 마찬가지로 프로토타입 기반의 객체 생성 메커니즘인 것.

  • 정적 메서드
class Cat {
// 생성자 역할을 합니다.
	constructor(name){
	// 인스턴스 생성 및 초기화 진행이 가능합니다.
	this.name = name;
	}
// 프로토타입 메서드
	meow(){console.log(this.name + ': 야옹')}
// 정적 메서드
	static staticMeow(){console.log('미야웅')}
}

Cat.staticMeow(); // 미야웅

정적 메서드는 클래스에 바인딩된 메서드로, 인스턴스와 달리 별도의 생성 과정이 필요없기 때문에 클래스로 호출이 가능하다.

생성자 함수와 클래스의 차이

  1. new 연산자
    JS에서는 생성자 함수뿐만이 아닌 다른 함수에도 new 연산자를 사용 가능하다. (생성자 함수가 아닌 함수를 생성자 함수로 호출 가능하고, 일반 함수에 new 연산자를 붙여서 생성자 함수로써 호출이 가능하다.)
    그에 반해 클래스는 new 연산자 없이 호출이 불가능하다.
  2. extends와 super
    extends상속과 관련된 키워드이고, super수퍼클래스의 constructor 호출과 수퍼클래스의 메서드 호출을 가능하게 하는 키워드이다.
// 부모 클래스인 Animal Class
class Animal {
	constructor(weight, height){
	this.weight = weight;
	this.height = height;
}
}
// 상속을 통해 animal 클래스를 확장할 수 있습니다.
class Bird extends Animal{
	fly(){
	return 'fly';
}
}

수퍼 클래스의 Animal을 상속 받아 사용하므로(정확히는 수퍼 클래스인 Animal의 constructor가 객체를 만들어 서브 클래스에게 전달) 서브 클래스의 constructor 내부에서는 꼭 super()를 불러 주어야 함.

constructor(width,height, color) {
		//super 클래스에서 width와 height를 상속받는 경우
	super(width,height);
	this.color = color;
}

만약 super 클래스에게서 그대로 상속을 받는다면 constructor를 생략할 수도 있지만, 서브 클래스에서도 초기화를 진행하고 싶다면 꼭 super()를 불러주고, 매개 변수에 전달할 인수도 필요함.

constructor(width, height, color){
		// super 클래스에게서 width와 height를 상속받는 경우
		super(width, height);
		// 서브 클래스 자체에서 필요한 프로퍼티를 초기화 시켜줍니다.
		this.color = color;
}

//상속 받는 매개 변수에 대한 인수도 같이 전달해 주어야 합니다.
const bird = new Bird(2,4,'red')
profile
코딩하는 고양이🐱 / UI Developer, Front-end Developer

0개의 댓글