PHP / Java에서 다음을 수행 할 수 있습니다.
class Sub extends Base
{
}
그리고 Super 클래스의 모든 공개 / 보호 된 메서드, 속성, 필드 등은 필요한 경우 재정의 할 수있는 Sub 클래스의 일부가됩니다.
Javascript에서 이에 상응하는 것은 무엇입니까?
PHP / Java에서 다음을 수행 할 수 있습니다.
class Sub extends Base
{
}
그리고 Super 클래스의 모든 공개 / 보호 된 메서드, 속성, 필드 등은 필요한 경우 재정의 할 수있는 Sub 클래스의 일부가됩니다.
Javascript에서 이에 상응하는 것은 무엇입니까?
답변:
나는 지금 이것을하는 방법을 변경했으며 생성자 함수와 그 prototype
속성을 사용하지 않으려 고 노력 했지만 2010의 이전 답변은 여전히 맨 아래에 있습니다. 나는 지금 선호한다 Object.create()
. Object.create
모든 최신 브라우저에서 사용할 수 있습니다.
나는 그주의해야한다 Object.create
일반적으로 훨씬 느린 사용하는 것보다 new
함수 생성자.
//The prototype is just an object when you use `Object.create()`
var Base = {};
//This is how you create an instance:
var baseInstance = Object.create(Base);
//If you want to inherit from "Base":
var subInstance = Object.create(Object.create(Base));
//Detect if subInstance is an instance of Base:
console.log(Base.isPrototypeOf(subInstance)); //True
Object.create 사용의 큰 이점 중 하나는 defineProperties 인수 를 전달할 수 있다는 것입니다.이 인수는 클래스의 속성에 액세스하고 열거 할 수있는 방법에 대한 중요한 제어를 제공하며, 함수를 사용하여 인스턴스를 생성합니다. 인스턴스를 반환하는 대신 끝에 초기화를 수행 할 수 있습니다.
var Base = {};
function createBase() {
return Object.create(Base, {
doSomething: {
value: function () {
console.log("Doing something");
},
},
});
}
var Sub = createBase();
function createSub() {
return Object.create(Sub, {
doSomethingElse: {
value: function () {
console.log("Doing something else");
},
},
});
}
var subInstance = createSub();
subInstance.doSomething(); //Logs "Doing something"
subInstance.doSomethingElse(); //Logs "Doing something else"
console.log(Base.isPrototypeOf(subInstance)); //Logs "true"
console.log(Sub.isPrototypeOf(subInstance)); //Logs "true
이것은 2010의 원래 답변입니다.
function Base ( ) {
this.color = "blue";
}
function Sub ( ) {
}
Sub.prototype = new Base( );
Sub.prototype.showColor = function ( ) {
console.log( this.color );
}
var instance = new Sub ( );
instance.showColor( ); //"blue"
JavaScript에는 클래스가 없지만 여러 가지 방법으로 상속 및 동작 재사용을 얻을 수 있습니다.
유사 클래식 상속 (프로토 타이핑을 통해) :
function Super () {
this.member1 = 'superMember1';
}
Super.prototype.member2 = 'superMember2';
function Sub() {
this.member3 = 'subMember3';
//...
}
Sub.prototype = new Super();
new
연산자 와 함께 사용해야합니다 .
var subInstance = new Sub();
함수 애플리케이션 또는 "생성자 체인":
function Super () {
this.member1 = 'superMember1';
this.member2 = 'superMember2';
}
function Sub() {
Super.apply(this, arguments);
this.member3 = 'subMember3';
}
이 접근 방식은 new
운영자 와 함께 사용해야합니다 .
var subInstance = new Sub();
첫 번째 예제와의 차이점 apply
은 Super
생성자가 this
내부 객체에 Sub
할당 될 때 this
on에 할당 된 속성을 Super
새 인스턴스에 직접 추가한다는 것입니다 ( 예 : subInstance
속성 포함 member1
및 member2
직접 ( subInstance.hasOwnProperty('member1') == true;
)).
첫 번째 예에서 이러한 속성은 프로토 타입 체인을 통해 도달 하며 내부 [[Prototype]]
개체 에 존재 합니다.
기생 상속 또는 전력 생성자 :
function createSuper() {
var obj = {
member1: 'superMember1',
member2: 'superMember2'
};
return obj;
}
function createSub() {
var obj = createSuper();
obj.member3 = 'subMember3';
return obj;
}
이 접근 방식은 기본적으로 "객체 확대"를 기반으로하며 new
연산자 를 사용할 필요가 없으며 보시 this
다시피 키워드가 관련되지 않습니다.
var subInstance = createSub();
ECMAScript 5th Ed. Object.create
방법:
// Check if native implementation available
if (typeof Object.create !== 'function') {
Object.create = function (o) {
function F() {} // empty constructor
F.prototype = o; // set base object as prototype
return new F(); // return empty object with right [[Prototype]]
};
}
var superInstance = {
member1: 'superMember1',
member2: 'superMember2'
};
var subInstance = Object.create(superInstance);
subInstance.member3 = 'subMember3';
위의 방법은 Crockford가 제안한 프로토 타입 상속 기법 입니다.
개체 인스턴스는 다른 개체 인스턴스에서 상속됩니다.
이 기술은 상속 된 속성이 모든 새 개체 인스턴스에 복사되지 않기 때문에 단순한 "개체 확대"보다 나을 수 있습니다 . 위의 예 에서는 속성 만 물리적으로 만 포함되어 있으므로 기본 개체가 확장 개체 [[Prototype]]
의 로 설정되어 있기 때문 입니다 .subInstance
member3
Object.create()
또는 사용자 정의 clone()
함수 (예 : mercurial.intuxication.org/hg/js-hacks/raw-file/tip/clone.js )를 사용하십시오. 설명은 stackoverflow.com/questions/1404559/…에 대한 주석을 참조하십시오
Object.create
방법 을 언급하려고했다 :)
member1
변수 를 공유하므로 전혀 바람직하지 않습니다. 물론 그들은 그것을 다시 쓸 수 있지만 그것은 의미가 없습니다. github.com/dotnetwise/Javascript-FastClass 는 더 나은 설탕 솔루션입니다.
Sub.prototype = new Super();
. 스크립트 실행 중에 두 클래스가 모두 사용되지 않으면 어떻게됩니까? 성능 문제인 것 같습니다. 자식 클래스가 실제로 사용되지 않는데 왜 부모 클래스를 만들어야합니까? 자세히 설명해 주시겠습니까? 다음은 문제에 대한 간단한 데모입니다. jsfiddle.net/slavafomin/ZeVL2 감사합니다!
ECMAScript 표준 (ES6) 의 최신 버전 에서는 키워드를 사용할 수 있습니다 class
.
클래스 정의는 일반이 아닙니다 object
. 따라서 클래스 멤버 사이에는 쉼표가 없습니다. 클래스의 인스턴스를 만들려면 new
키워드 를 사용해야합니다 . 기본 클래스에서 상속하려면 다음을 사용하십시오 extends
.
class Vehicle {
constructor(name) {
this.name = name;
this.kind = 'vehicle';
}
getName() {
return this.name;
}
}
// Create an instance
var myVehicle = new Vehicle('rocky');
myVehicle.getName(); // => 'rocky'
기본 클래스에서 상속하려면 다음을 사용하십시오 extends
.
class Car extends Vehicle {
constructor(name) {
super(name);
this.kind = 'car'
}
}
var myCar = new Car('bumpy');
myCar.getName(); // => 'bumpy'
myCar instanceof Car; // => true
myCar instanceof Vehicle; // => true
파생 클래스에서 생성자 또는 메서드의 super를 사용하여 기본 클래스에 액세스 할 수 있습니다.
super().
super.getName()
.클래스 사용에 더 많은 것이 있습니다. 이 주제에 대해 더 자세히 알고 싶다면 Axel Rauschmayer 박사의 “ Classes in ECMAScript 6 ”을 추천합니다. *
자, JavaScript에는 "클래스 상속"이없고 "프로토 타입 상속"만 있습니다. 따라서 클래스 "트럭"을 만들고 "자동차"의 하위 클래스로 표시하지 않습니다. 대신 개체 "Jack"을 만들고 "John"을 프로토 타입으로 사용한다고 말합니다. John이 "4 + 4"가 얼마인지 안다면 Jack도 알고 있습니다.
http://javascript.crockford.com/prototypal.html http://javascript.crockford.com/prototypal.html 여기에서 Douglas Crockford의 프로토 타입 상속에 대한 기사를 읽어 보시기 바랍니다. 그는 또한 JavaScript가 다른 OO 언어에서와 같이 "유사한"상속을 갖도록 만드는 방법을 보여준 다음이를 설명합니다. 실제로는 사용되지 않는 방식으로 자바 스크립트를 깨는 것을 의미합니다.
나는이 인용문이 가장 깨달음을 얻는다.
본질적으로 JavaScript "클래스" 는 생성자 역할을하는 Function 객체와 첨부 된 프로토 타입 객체입니다. ( 출처 : Guru Katz )
저는 객체보다는 생성자를 사용하는 것을 좋아하기 때문에 여기에서 CMS가 설명 하는 "의사-고전적 상속"방법에 부분적 입니다. 다음은 프로토 타입 체인을 사용한 다중 상속 의 예입니다 .
// Lifeform "Class" (Constructor function, No prototype)
function Lifeform () {
this.isLifeform = true;
}
// Animal "Class" (Constructor function + prototype for inheritance)
function Animal () {
this.isAnimal = true;
}
Animal.prototype = new Lifeform();
// Mammal "Class" (Constructor function + prototype for inheritance)
function Mammal () {
this.isMammal = true;
}
Mammal.prototype = new Animal();
// Cat "Class" (Constructor function + prototype for inheritance)
function Cat (species) {
this.isCat = true;
this.species = species
}
Cat.prototype = new Mammal();
// Make an instance object of the Cat "Class"
var tiger = new Cat("tiger");
console.log(tiger);
// The console outputs a Cat object with all the properties from all "classes"
console.log(tiger.isCat, tiger.isMammal, tiger.isAnimal, tiger.isLifeform);
// Outputs: true true true true
// You can see that all of these "is" properties are available in this object
// We can check to see which properties are really part of the instance object
console.log( "tiger hasOwnProperty: "
,tiger.hasOwnProperty("isLifeform") // false
,tiger.hasOwnProperty("isAnimal") // false
,tiger.hasOwnProperty("isMammal") // false
,tiger.hasOwnProperty("isCat") // true
);
// New properties can be added to the prototypes of any
// of the "classes" above and they will be usable by the instance
Lifeform.prototype.A = 1;
Animal.prototype.B = 2;
Mammal.prototype.C = 3;
Cat.prototype.D = 4;
console.log(tiger.A, tiger.B, tiger.C, tiger.D);
// Console outputs: 1 2 3 4
// Look at the instance object again
console.log(tiger);
// You'll see it now has the "D" property
// The others are accessible but not visible (console issue?)
// In the Chrome console you should be able to drill down the __proto__ chain
// You can also look down the proto chain with Object.getPrototypeOf
// (Equivalent to tiger.__proto__)
console.log( Object.getPrototypeOf(tiger) ); // Mammal
console.log( Object.getPrototypeOf(Object.getPrototypeOf(tiger)) ); // Animal
// Etc. to get to Lifeform
여기에 MDN의 또 다른 좋은 리소스가 있으며 여기 에 jsfiddle이 있으므로 사용해 볼 수 있습니다 .
Javascript 상속은 실제로 클래스가 없기 때문에 Java 및 PHP와 약간 다릅니다. 대신 메서드와 멤버 변수를 제공하는 프로토 타입 개체가 있습니다. 이러한 프로토 타입을 연결하여 개체 상속을 제공 할 수 있습니다. 이 질문을 조사 할 때 내가 찾은 가장 일반적인 패턴은 Mozilla 개발자 네트워크 에 설명되어 있습니다. 수퍼 클래스 메서드에 대한 호출을 포함하고 경고 메시지에 로그를 표시하도록 예제를 업데이트했습니다.
// Shape - superclass
function Shape() {
this.x = 0;
this.y = 0;
}
// superclass method
Shape.prototype.move = function(x, y) {
this.x += x;
this.y += y;
log += 'Shape moved.\n';
};
// Rectangle - subclass
function Rectangle() {
Shape.call(this); // call super constructor.
}
// subclass extends superclass
Rectangle.prototype = Object.create(Shape.prototype);
Rectangle.prototype.constructor = Rectangle;
// Override method
Rectangle.prototype.move = function(x, y) {
Shape.prototype.move.call(this, x, y); // call superclass method
log += 'Rectangle moved.\n';
}
var log = "";
var rect = new Rectangle();
log += ('Is rect an instance of Rectangle? ' + (rect instanceof Rectangle) + '\n'); // true
log += ('Is rect an instance of Shape? ' + (rect instanceof Shape) + '\n'); // true
rect.move(1, 1); // Outputs, 'Shape moved.'
alert(log);
개인적으로 Javascript의 상속이 어색하다고 생각하지만 이것이 내가 찾은 최고의 버전입니다.
.inheritWith
및 .fastClass
라이브러리 를 사용할 수 있습니다 . 가장 인기있는 라이브러리보다 빠르며 때로는 기본 버전보다 빠릅니다.
사용하기 매우 쉬움 :
function Super() {
this.member1 = "superMember";//instance member
}.define({ //define methods on Super's prototype
method1: function() { console.log('super'); } //prototype member
}.defineStatic({ //define static methods directly on Super function
staticMethod1: function() { console.log('static method on Super'); }
});
var Sub = Super.inheritWith(function(base, baseCtor) {
return {
constructor: function() {//the Sub constructor that will be returned to variable Sub
this.member3 = 'subMember3'; //instance member on Sub
baseCtor.apply(this, arguments);//call base construcor and passing all incoming arguments
},
method1: function() {
console.log('sub');
base.method1.apply(this, arguments); //call the base class' method1 function
}
}
용법
var s = new Sub();
s.method1(); //prints:
//sub
//super
function Person(attr){
this.name = (attr && attr.name)? attr.name : undefined;
this.birthYear = (attr && attr.birthYear)? attr.birthYear : undefined;
this.printName = function(){
console.log(this.name);
}
this.printBirthYear = function(){
console.log(this.birthYear);
}
this.print = function(){
console.log(this.name + '(' +this.birthYear+ ')');
}
}
function PersonExt(attr){
Person.call(this, attr);
this.print = function(){
console.log(this.name+ '-' + this.birthYear);
}
this.newPrint = function(){
console.log('New method');
}
}
PersonExt.prototype = new Person();
// Init object and call methods
var p = new Person({name: 'Mr. A', birthYear: 2007});
// Parent method
p.print() // Mr. A(2007)
p.printName() // Mr. A
var pExt = new PersonExt({name: 'Mr. A', birthYear: 2007});
// Overwriten method
pExt.print() // Mr. A-2007
// Extended method
pExt.newPrint() // New method
// Parent method
pExt.printName() // Mr. A
많은 게시물을 읽은 후이 솔루션을 생각해 냈습니다 ( jsfiddle here ). 대부분의 경우 더 정교한 것이 필요하지 않습니다.
var Class = function(definition) {
var base = definition.extend || null;
var construct = definition.construct || definition.extend || function() {};
var newClass = function() {
this._base_ = base;
construct.apply(this, arguments);
}
if (definition.name)
newClass._name_ = definition.name;
if (definition.extend) {
var f = function() {}
f.prototype = definition.extend.prototype;
newClass.prototype = new f();
newClass.prototype.constructor = newClass;
newClass._extend_ = definition.extend;
newClass._base_ = definition.extend.prototype;
}
if (definition.statics)
for (var n in definition.statics) newClass[n] = definition.statics[n];
if (definition.members)
for (var n in definition.members) newClass.prototype[n] = definition.members[n];
return newClass;
}
var Animal = Class({
construct: function() {
},
members: {
speak: function() {
console.log("nuf said");
},
isA: function() {
return "animal";
}
}
});
var Dog = Class({ extend: Animal,
construct: function(name) {
this._base_();
this.name = name;
},
statics: {
Home: "House",
Food: "Meat",
Speak: "Barks"
},
members: {
name: "",
speak: function() {
console.log( "ouaf !");
},
isA: function(advice) {
return advice + " dog -> " + Dog._base_.isA.call(this);
}
}
});
var Yorkshire = Class({ extend: Dog,
construct: function(name,gender) {
this._base_(name);
this.gender = gender;
},
members: {
speak: function() {
console.log( "ouin !");
},
isA: function(advice) {
return "yorkshire -> " + Yorkshire._base_.isA.call(this,advice);
}
}
});
var Bulldog = function() { return _class_ = Class({ extend: Dog,
construct: function(name) {
this._base_(name);
},
members: {
speak: function() {
console.log( "OUAF !");
},
isA: function(advice) {
return "bulldog -> " + _class_._base_.isA.call(this,advice);
}
}
})}();
var animal = new Animal("Maciste");
console.log(animal.isA());
animal.speak();
var dog = new Dog("Sultan");
console.log(dog.isA("good"));
dog.speak();
var yorkshire = new Yorkshire("Golgoth","Male");
console.log(yorkshire.isA("bad"));
yorkshire.speak();
var bulldog = new Bulldog("Mike");
console.log(bulldog.isA("nice"));
bulldog.speak();
CMS의 답변 덕분에 잠시 동안 프로토 타입과 Object.create를 조작 한 후 여기에 표시된대로 apply를 사용하여 상속에 대한 깔끔한 솔루션을 찾을 수있었습니다.
var myNamespace = myNamespace || (function() {
return {
BaseClass: function(){
this.someBaseProperty = "someBaseProperty";
this.someProperty = "BaseClass";
this.someFunc = null;
},
DerivedClass:function(someFunc){
myNamespace.BaseClass.apply(this, arguments);
this.someFunc = someFunc;
this.someProperty = "DerivedClass";
},
MoreDerivedClass:function(someFunc){
myNamespace.DerivedClass.apply(this, arguments);
this.someFunc = someFunc;
this.someProperty = "MoreDerivedClass";
}
};
})();
ES2015에서 JavaScript에서 상속을하는 방법입니다.
class Sub extends Base {
}
function Base() {
this.doSomething = function () {
}
}
function Sub() {
Base.call(this); // inherit Base's method(s) to this instance of Sub
}
var sub = new Sub();
sub.doSomething();
Javascript에는 클래스가 없습니다. 자바 스크립트의 클래스는 자바 스크립트의 프로토 타입 상속 패턴 위에 구축 된 구문 적 설탕 일뿐 입니다. JS class
를 사용하여 프로토 타입 상속을 적용 할 수 있지만 실제로 여전히 내부에서 생성자 함수를 사용하고 있음을 인식하는 것이 중요합니다.
이러한 개념 es6
은 extends 키워드를 사용하여 '클래스' 에서 확장 할 때도 적용됩니다 . 이것은 프로토 타입 체인에 추가 링크를 생성합니다. 그만큼__proto__
class Animal {
makeSound () {
console.log('animalSound');
}
}
class Dog extends Animal {
makeSound () {
console.log('Woof');
}
}
console.log(typeof Dog) // classes in JS are just constructor functions under the hood
const dog = new Dog();
console.log(dog.__proto__ === Dog.prototype);
// First link in the prototype chain is Dog.prototype
console.log(dog.__proto__.__proto__ === Animal.prototype);
// Second link in the prototype chain is Animal.prototype
// The extends keyword places Animal in the prototype chain
// Now Dog 'inherits' the makeSound property from Animal
Object.create()
또한 자바 스크립트에서 JS에서 상속을 만드는 방법입니다. Object.create()
는 새 객체를 생성하는 함수이며은 기존 객체를 인수로 사용합니다. __proto__
새로 생성 된 객체 의 속성에 인자로받은 객체를 할당 합니다. 다시 말하지만 우리가 JS가 구현하는 프로토 타입 상속 패러다임에 묶여 있음을 깨닫는 것이 중요합니다.
const Dog = {
fluffy: true,
bark: () => {
console.log('woof im a relatively cute dog or something else??');
}
};
const dog = Object.create(Dog);
dog.bark();
JavaScript에는 클래스가 없기 때문에 JavaScript의 클래스에서 상속 할 수 없습니다.