자바 스크립트 확장 클래스
기본 클래스가 있습니다.
function Monster() {
this.health = 100;
}
Monster.prototype.growl = function() {
console.log("Grr!");
}
확장하고 다른 클래스를 만들고 싶습니다.
function Monkey extends Monster() {
this.bananaCount = 5;
}
Monkey.prototype.eatBanana {
this.bananaCount--;
this.health++; //Accessing variable from parent class monster
this.growl(); //Accessing function from parent class monster
}
나는 꽤 많은 연구를 해왔고 JavaScript에서 이것을하기위한 복잡한 솔루션이 많이있는 것 같습니다. JS에서 이것을 수행하는 가장 간단하고 안정적인 방법은 무엇입니까?
ES6에 대해 아래 업데이트 됨
2013 년 3 월 및 ES5
이 MDN 문서는 클래스 확장을 잘 설명합니다.
https://developer.mozilla.org/en-US/docs/JavaScript/Introduction_to_Object-Oriented_JavaScript
특히, 이제 그들은 그것을 처리합니다.
// define the Person Class
function Person() {}
Person.prototype.walk = function(){
alert ('I am walking!');
};
Person.prototype.sayHello = function(){
alert ('hello');
};
// define the Student class
function Student() {
// Call the parent constructor
Person.call(this);
}
// inherit Person
Student.prototype = Object.create(Person.prototype);
// correct the constructor pointer because it points to Person
Student.prototype.constructor = Student;
// replace the sayHello method
Student.prototype.sayHello = function(){
alert('hi, I am a student');
}
// add sayGoodBye method
Student.prototype.sayGoodBye = function(){
alert('goodBye');
}
var student1 = new Student();
student1.sayHello();
student1.walk();
student1.sayGoodBye();
// check inheritance
alert(student1 instanceof Person); // true
alert(student1 instanceof Student); // true
참고 Object.create()
IE8 등 일부 이전 버전의 브라우저에서 지원되지 않습니다 :
이를 지원해야하는 위치에있는 경우 링크 된 MDN 문서는 polyfill 또는 다음과 같은 근사치를 사용하도록 제안합니다.
function createObject(proto) {
function ctor() { }
ctor.prototype = proto;
return new ctor();
}
이 같은를 사용하여 Student.prototype = createObject(Person.prototype)
사용하는 것이 바람직하다 new Person()
는 점에서 부모의 생성자 함수를 호출 방지 프로토 타입을 상속 할 때, 오직 상속인의 생성자가 호출되고 부모 생성자를 호출합니다.
2017 년 5 월 및 ES6
고맙게도 JavaScript 디자이너들은 도움을 요청하는 우리의 간청을 듣고이 문제에 접근하는 더 적절한 방법을 채택했습니다.
MDN 은 ES6 클래스 상속에 대한 또 다른 훌륭한 예를 가지고 있지만 위의 ES6에서 재현 한 것과 똑같은 클래스 집합을 보여 드리겠습니다.
class Person {
sayHello() {
alert('hello');
}
walk() {
alert('I am walking!');
}
}
class Student extends Person {
sayGoodBye() {
alert('goodBye');
}
sayHello() {
alert('hi, I am a student');
}
}
var student1 = new Student();
student1.sayHello();
student1.walk();
student1.sayGoodBye();
// check inheritance
alert(student1 instanceof Person); // true
alert(student1 instanceof Student); // true
우리 모두가 원하는 것처럼 깨끗하고 이해할 수 있습니다. ES6는 매우 일반적이지만 모든 곳에서 지원되지는 않습니다 .
ES6는 사용 지금 기회를 제공 클래스 및 확장 키워드 :
그러면 코드는 다음과 같습니다.
기본 클래스가 있습니다.
class Monster{
constructor(){
this.health = 100;
}
growl() {
console.log("Grr!");
}
}
다음을 사용하여 다른 클래스를 확장하고 생성하려는 것 :
class Monkey extends Monster {
constructor(){
super(); //don't forget "super"
this.bananaCount = 5;
}
eatBanana() {
this.bananaCount--;
this.health++; //Accessing variable from parent class monster
this.growl(); //Accessing function from parent class monster
}
}
이 시도:
Function.prototype.extends = function(parent) {
this.prototype = Object.create(parent.prototype);
};
Monkey.extends(Monster);
function Monkey() {
Monster.apply(this, arguments); // call super
}
편집 : http://jsbin.com/anekew/1/edit 여기에 간단한 데모를 넣었습니다 . 주 extends
JS에서 예약어이며 코드를 linting 때 경고를받을 수 있습니다, 당신은 단순히 이름을 지정할 수 있습니다 inherits
나는 보통 무엇이다 그.
이 도우미를 배치하고 객체 props
를 매개 변수로만 사용하면 JS의 상속이 조금 더 간단 해집니다.
Function.prototype.inherits = function(parent) {
this.prototype = Object.create(parent.prototype);
};
function Monster(props) {
this.health = props.health || 100;
}
Monster.prototype = {
growl: function() {
return 'Grrrrr';
}
};
Monkey.inherits(Monster);
function Monkey() {
Monster.apply(this, arguments);
}
var monkey = new Monkey({ health: 200 });
console.log(monkey.health); //=> 200
console.log(monkey.growl()); //=> "Grrrr"
프로토 타입 방식이 마음에 들지 않으면 OOP 방식으로 작동하지 않기 때문에 다음을 시도해 볼 수 있습니다.
var BaseClass = function()
{
this.some_var = "foobar";
/**
* @return string
*/
this.someMethod = function() {
return this.some_var;
}
};
var MyClass = new Class({ extends: BaseClass }, function()
{
/**
* @param string value
*/
this.__construct = function(value)
{
this.some_var = value;
}
})
경량 라이브러리 사용 (2k 축소됨) : https://github.com/haroldiedema/joii
나는 하나의 변형을 제안 할 수 있으며, 책에서 읽었을 때 가장 간단 해 보입니다.
function Parent() {
this.name = 'default name';
};
function Child() {
this.address = '11 street';
};
Child.prototype = new Parent(); // child class inherits from Parent
Child.prototype.constructor = Child; // constructor alignment
var a = new Child();
console.log(a.name); // "default name" trying to reach property of inherited class
이것은 인스턴스 메서드에 대한 세부 사항을 포함하고 질문의 해당 측면에 대한 확장 가능한 접근 방식을 취하는 elclanrs의 솔루션의 확장입니다 (말장난을 실례합니다). David Flanagan의 "JavaScript : The Definitive Guide"(이 문맥에 맞게 부분적으로 조정 됨) 덕분에이 내용이 통합되었음을 전적으로 인정합니다. 이것은 다른 솔루션보다 분명히 더 장황하지만 장기적으로는 도움이 될 것입니다.
먼저 David의 간단한 "확장"함수를 사용하여 속성을 지정된 개체에 복사합니다.
function extend(o,p) {
for (var prop in p) {
o[prop] = p[prop];
}
return o;
}
그런 다음 그의 하위 클래스 정의 유틸리티를 구현합니다.
function defineSubclass(superclass, // Constructor of our superclass
constructor, // Constructor of our new subclass
methods, // Instance methods
statics) { // Class properties
// Set up the prototype object of the subclass
constructor.prototype = Object.create(superclass.prototype);
constructor.prototype.constructor = constructor;
if (methods) extend(constructor.prototype, methods);
if (statics) extend(constructor, statics);
return constructor;
}
마지막 준비를 위해 David의 새로운 jiggery-pokery로 Function 프로토 타입을 향상시킵니다.
Function.prototype.extend = function(constructor, methods, statics) {
return defineSubclass(this, constructor, methods, statics);
};
Monster 클래스를 정의한 후 다음을 수행합니다 (확장 / 상속하려는 새 클래스에 재사용 가능).
var Monkey = Monster.extend(
// constructor
function Monkey() {
this.bananaCount = 5;
Monster.apply(this, arguments); // Superclass()
},
// methods added to prototype
{
eatBanana: function () {
this.bananaCount--;
this.health++;
this.growl();
}
}
);
전통적인 확장의 경우 수퍼 클래스를 생성자 함수로 작성한 다음 상속 된 클래스에이 생성자를 적용 할 수 있습니다.
function AbstractClass() {
this.superclass_method = function(message) {
// do something
};
}
function Child() {
AbstractClass.apply(this);
// Now Child will have superclass_method()
}
angularjs의 예 :
http://plnkr.co/edit/eFixlsgF3nJ1LeWUJKsd?p=preview
app.service('noisyThing',
['notify',function(notify){
this._constructor = function() {
this.scream = function(message) {
message = message + " by " + this.get_mouth();
notify(message);
console.log(message);
};
this.get_mouth = function(){
return 'abstract mouth';
}
}
}])
.service('cat',
['noisyThing', function(noisyThing){
noisyThing._constructor.apply(this)
this.meow = function() {
this.scream('meooooow');
}
this.get_mouth = function(){
return 'fluffy mouth';
}
}])
.service('bird',
['noisyThing', function(noisyThing){
noisyThing._constructor.apply(this)
this.twit = function() {
this.scream('fuuuuuuck');
}
}])
Autodidacts :
function BaseClass(toBePrivate){
var morePrivates;
this.isNotPrivate = 'I know';
// add your stuff
}
var o = BaseClass.prototype;
// add your prototype stuff
o.stuff_is_never_private = 'whatever_except_getter_and_setter';
// MiddleClass extends BaseClass
function MiddleClass(toBePrivate){
BaseClass.call(this);
// add your stuff
var morePrivates;
this.isNotPrivate = 'I know';
}
var o = MiddleClass.prototype = Object.create(BaseClass.prototype);
MiddleClass.prototype.constructor = MiddleClass;
// add your prototype stuff
o.stuff_is_never_private = 'whatever_except_getter_and_setter';
// TopClass extends MiddleClass
function TopClass(toBePrivate){
MiddleClass.call(this);
// add your stuff
var morePrivates;
this.isNotPrivate = 'I know';
}
var o = TopClass.prototype = Object.create(MiddleClass.prototype);
TopClass.prototype.constructor = TopClass;
// add your prototype stuff
o.stuff_is_never_private = 'whatever_except_getter_and_setter';
// to be continued...
getter 및 setter를 사용하여 "인스턴스"를 만듭니다.
function doNotExtendMe(toBePrivate){
var morePrivates;
return {
// add getters, setters and any stuff you want
}
}
요약:
자바 스크립트에서 프로토 타입으로 생성자 함수를 확장하는 문제를 해결할 수있는 여러 가지 방법이 있습니다. 이러한 방법 중 '최상의'솔루션은 의견 기반입니다. 그러나 생성자의 함수 프로토 타입을 확장하기 위해 자주 사용되는 두 가지 메서드가 있습니다.
ES 2015 수업 :
class Monster {
constructor(health) {
this.health = health
}
growl () {
console.log("Grr!");
}
}
class Monkey extends Monster {
constructor (health) {
super(health) // call super to execute the constructor function of Monster
this.bananaCount = 5;
}
}
const monkey = new Monkey(50);
console.log(typeof Monster);
console.log(monkey);
The above approach of using ES 2015
classes is nothing more than syntactic sugar over the prototypal inheritance pattern in javascript. Here the first log where we evaluate typeof Monster
we can observe that this is function. This is because classes are just constructor functions under the hood. Nonetheless you may like this way of implementing prototypal inheritance and definitively should learn it. It is used in major frameworks such as ReactJS
and Angular2+
.
Factory function using Object.create()
:
function makeMonkey (bananaCount) {
// here we define the prototype
const Monster = {
health: 100,
growl: function() {
console.log("Grr!");}
}
const monkey = Object.create(Monster);
monkey.bananaCount = bananaCount;
return monkey;
}
const chimp = makeMonkey(30);
chimp.growl();
console.log(chimp.bananaCount);
이 메서드는 Object.create()
반환하는 새로 생성 된 객체의 프로토 타입이 될 객체를 취하는 메서드를 사용 합니다. 따라서 먼저이 함수에서 프로토 타입 객체를 만든 다음 속성이 Monster 객체로 설정된 Object.create()
빈 객체를 반환하는 호출 __proto__
합니다. 그런 다음 객체의 모든 속성을 초기화 할 수 있습니다.이 예제에서는 새로 생성 된 객체에 bananacount를 할당합니다.
위의 많은 답변과 달리 절대적으로 최소 (그리고 올바른) 버전은 다음과 같습니다.
function Monkey(param){
this.someProperty = param;
}
Monkey.prototype = Object.create(Monster.prototype);
Monkey.prototype.eatBanana = function(banana){ banana.eat() }
그게 다야. 여기에서 더 긴 설명을 읽을 수 있습니다.
참고 URL : https://stackoverflow.com/questions/15192722/javascript-extending-class
'Development Tip' 카테고리의 다른 글
공백으로 문자열을 분할하고 정규 표현식을 사용하여 선행 및 후행 공백을 단어 배열로 무시하는 방법은 무엇입니까? (0) | 2020.11.03 |
---|---|
슬러그에 의한 WordPress 쿼리 단일 게시물 (0) | 2020.11.03 |
"IIS Express 웹 서버를 시작할 수 없습니다." (0) | 2020.11.03 |
.NET 소스 코드가 디버깅 중단 점을 하드 코딩 할 수 있습니까? (0) | 2020.11.03 |
Java 맵 항목 업데이트 (0) | 2020.11.03 |