일반 {...}
구문을 사용하면 하나의 객체를 생성할 수 있습니다. 하지만 여러 사용자나 메뉴 항목 등과 같은 유사한 개체를 많이 만들어야 하는 경우가 많습니다.
이는 생성자 함수와 "new"
연산자를 사용하여 수행할 수 있습니다.
생성자 함수는 기술적으로 일반 함수입니다. 하지만 두 가지 규칙이 있습니다.
대문자로 먼저 이름이 지정됩니다.
"new"
연산자로만 실행해야 합니다.
예를 들어:
함수 사용자(이름) { this.name = 이름; this.isAdmin = 거짓; } let user = new User("잭"); 경고(사용자.이름); // 잭 경고(user.isAdmin); // 거짓
함수가 new
로 실행되면 다음 단계를 수행합니다.
새로운 빈 객체가 생성되어 this
에 할당됩니다.
함수 본문이 실행됩니다. 일반적으로 this
수정하고 새 속성을 추가합니다.
this
값이 반환됩니다.
즉, new User(...)
다음과 같은 작업을 수행합니다.
함수 사용자(이름) { // 이 = {}; (암시적으로) // 여기에 속성을 추가합니다. this.name = 이름; this.isAdmin = 거짓; // 이것을 반환합니다; (암시적으로) }
따라서 let user = new User("Jack")
다음과 같은 결과를 제공합니다.
사용자 = { 이름: "잭", isAdmin: 거짓 };
이제 다른 사용자를 생성하려면 new User("Ann")
, new User("Alice")
등을 호출하면 됩니다. 매번 리터럴을 사용하는 것보다 훨씬 짧고 읽기 쉽습니다.
재사용 가능한 객체 생성 코드를 구현하는 것이 생성자의 주요 목적입니다.
다시 한 번 알아두세요. 기술적으로 모든 함수( this
없는 화살표 함수 제외)를 생성자로 사용할 수 있습니다. new
로 실행될 수 있으며 위의 알고리즘이 실행됩니다. "대문자 우선"은 함수가 new
로 실행된다는 것을 분명히 하기 위한 일반적인 합의입니다.
새로운 함수() { … }
하나의 복잡한 객체 생성에 관한 많은 코드 라인이 있는 경우 다음과 같이 즉시 호출되는 생성자 함수로 이를 래핑할 수 있습니다.
// 함수를 생성하고 즉시 new로 호출합니다. 사용자 = 새 함수() { this.name = "존"; this.isAdmin = 거짓; // ...사용자 생성을 위한 다른 코드 // 어쩌면 복잡한 논리와 문장일 수도 있음 // 지역 변수 등 };
이 생성자는 어디에도 저장되지 않고 생성되고 호출되기 때문에 다시 호출할 수 없습니다. 따라서 이 트릭은 향후 재사용 없이 단일 객체를 구성하는 코드를 캡슐화하는 것을 목표로 합니다.
고급 기능
이 섹션의 구문은 거의 사용되지 않으므로 모든 내용을 알고 싶지 않으면 건너뛰세요.
함수 내에서 특별한 new.target
속성을 사용하여 new
사용하여 호출되었는지 여부를 확인할 수 있습니다.
일반 호출에 대해서는 정의되지 않으며 new
로 호출되는 경우 함수와 같습니다.
함수 사용자() { 경고(new.target); } // "새" 없이: 사용자(); // 한정되지 않은 // "새"로: 새로운 사용자(); // 함수 사용자 { ... }
이는 함수 내부에서 new
사용하여 "생성자 모드에서" 호출되었는지 또는 new 없이 "일반 모드에서" 호출되었는지 알 수 있습니다.
다음과 같이 new
호출과 일반 호출을 모두 수행하여 동일한 작업을 수행할 수도 있습니다.
함수 사용자(이름) { if (!new.target) { // new 없이 실행하는 경우 새로운 사용자(이름)을 반환합니다. // ...새 항목을 추가하겠습니다. } this.name = 이름; } john = User("John"); // 호출을 새 사용자에게 리디렉션합니다. 경고(존.이름); // 존
이 접근 방식은 구문을 보다 유연하게 만들기 위해 라이브러리에서 때때로 사용됩니다. 그래서 사람들은 new
사용하거나 사용하지 않고 함수를 호출할 수 있으며 여전히 작동합니다.
하지만 new
생략하면 무슨 일이 일어나고 있는지 좀 덜 명확해지기 때문에 어디에서나 사용하는 것은 좋지 않을 것입니다. new
사용하면 우리 모두는 새로운 객체가 생성된다는 것을 알고 있습니다.
일반적으로 생성자에는 return
문이 없습니다. 이들의 임무는 필요한 모든 내용을 this
에 작성하는 것이며 자동으로 결과가 됩니다.
그러나 return
문이 있는 경우 규칙은 간단합니다.
return
객체와 함께 호출되면 this
대신 객체가 반환됩니다.
return
이 프리미티브와 함께 호출되면 무시됩니다.
즉, 객체와 함께 return
해당 객체가 반환되고, 다른 모든 경우에는 this
반환됩니다.
예를 들어 여기서 return
객체를 반환하여 this
재정의합니다.
함수 BigUser() { this.name = "존"; return { 이름: "고질라" }; // <-- 이 객체를 반환합니다. } 경고( new BigUser().name ); // 고질라, 그 물건을 얻었어
그리고 여기에 빈 return
이 있는 예가 있습니다(또는 그 뒤에 기본 요소를 배치할 수도 있지만 중요하지 않습니다).
함수 SmallUser() { this.name = "존"; 반품; // <-- 이것을 반환합니다. } 경고( new SmallUser().name ); // 존
일반적으로 생성자에는 return
문이 없습니다. 여기서는 주로 완전성을 위해 객체를 반환하는 특별한 동작을 언급합니다.
괄호 생략
그런데 new
다음에 괄호를 생략할 수 있습니다.
사용자 = 새 사용자로 설정; // <-- 괄호 없음 //동일 사용자 = 새로운 사용자()를 보자;
여기서 괄호를 생략하는 것은 "좋은 스타일"로 간주되지 않지만 사양에 따라 구문이 허용됩니다.
생성자 함수를 사용하여 객체를 생성하면 상당한 유연성이 제공됩니다. 생성자 함수에는 객체를 생성하는 방법과 객체에 무엇을 넣을지 정의하는 매개변수가 있을 수 있습니다.
물론 this
에 속성뿐만 아니라 메서드도 추가할 수 있습니다.
예를 들어, 아래의 new User(name)
주어진 name
과 sayHi
메소드를 가진 객체를 생성합니다:
함수 사용자(이름) { this.name = 이름; this.sayHi = 함수() { Alert( "내 이름은: " + this.name ); }; } john = new User("John"); john.sayHi(); // 내 이름은: 존 /* 존 = { 이름: "존", sayHi: function() { ... } } */
복잡한 객체를 생성하기 위해 나중에 다루게 될 고급 구문인 클래스가 있습니다.
생성자 함수, 간단히 말해서 생성자는 일반 함수이지만 먼저 대문자로 이름을 지정하는 데 공통된 합의가 있습니다.
생성자 함수는 new
사용해서만 호출해야 합니다. 이러한 호출은 처음에 빈 this
를 만들고 마지막에 채워진 것을 반환하는 것을 의미합니다.
생성자 함수를 사용하여 유사한 개체를 여러 개 만들 수 있습니다.
JavaScript는 날짜에 대한 Date
, 집합에 대한 Set
및 우리가 연구할 기타 항목과 같은 많은 내장 언어 개체에 대한 생성자 함수를 제공합니다.
개체들아, 우리는 돌아올 것이다!
이 장에서는 객체와 생성자에 대한 기본 사항만 다룹니다. 이는 다음 장에서 데이터 유형과 기능에 대해 자세히 알아보는 데 필수적입니다.
이를 배운 후에는 객체로 돌아가서 프로토타입, 상속 및 클래스 장에서 심도 있게 다룹니다.
중요도: 2
new A() == new B()
가 되도록 함수 A
와 B
만드는 것이 가능합니까?
함수 A() { ... } 함수 B() { ... } a = new A(); b = 새로운 B()로 두십시오; 경고( a == b ); // 진실
그렇다면 코드의 예를 제공하십시오.
예, 가능합니다.
함수가 객체를 반환하면 new
this
대신 객체를 반환합니다.
예를 들어, 외부에서 정의된 동일한 객체 obj
반환할 수 있습니다.
obj = {}로 놔두세요; 함수 A() { 반환 obj; } 함수 B() { 반환 obj; } 경고( new A() == new B() ); // 진실
중요도: 5
3가지 메서드를 사용하여 객체를 생성하는 생성자 함수 Calculator
만듭니다.
read()
두 개의 값을 입력하라는 메시지를 표시하고 이를 각각 이름이 a
와 b
인 개체 속성으로 저장합니다.
sum()
이러한 속성의 합계를 반환합니다.
mul()
이러한 속성의 곱셈 결과를 반환합니다.
예를 들어:
계산기 = new Calculator(); 계산기.read(); 경고( "합계=" + Calculator.sum() ); 경고( "Mul=" + Calculator.mul() );
데모 실행
테스트를 통해 샌드박스를 엽니다.
함수 계산기() { this.read = 함수() { this.a = +prompt('a?', 0); this.b = +prompt('b?', 0); }; this.sum = 함수() { this.a + this.b를 반환합니다. }; this.mul = 함수() { return this.a * this.b; }; } 계산기 = new Calculator(); 계산기.read(); 경고( "합계=" + Calculator.sum() ); 경고( "Mul=" + Calculator.mul() );
샌드박스에서 테스트를 통해 솔루션을 엽니다.
중요도: 5
생성자 함수 Accumulator(startingValue)
만듭니다.
생성되는 개체는 다음과 같아야 합니다.
속성 value
에 "현재 값"을 저장합니다. 시작 값은 생성자 startingValue
의 인수로 설정됩니다.
read()
메서드는 prompt
사용하여 새 숫자를 읽고 이를 value
에 추가해야 합니다.
즉, value
속성은 초기 값인 startingValue
와 함께 사용자가 입력한 모든 값의 합계입니다.
코드 데모는 다음과 같습니다.
let accumulator = new Accumulator(1); // 초기값 1 Accumulator.read(); // 사용자가 입력한 값을 추가합니다. Accumulator.read(); // 사용자가 입력한 값을 추가합니다. 경고(누산기.값); // 이 값들의 합을 보여줍니다.
데모 실행
테스트를 통해 샌드박스를 엽니다.
함수 누산기(startingValue) { this.value = 시작값; this.read = 함수() { this.value += +prompt('얼마나 더할 것인가?', 0); }; } let accumulator = new Accumulator(1); Accumulator.read(); Accumulator.read(); 경고(누산기.값);
샌드박스에서 테스트를 통해 솔루션을 엽니다.