จะสืบทอดจากคลาสใน JavaScript ได้อย่างไร?


101

ใน PHP / Java สามารถทำได้:

class Sub extends Base
{
}

และโดยอัตโนมัติเมธอดสาธารณะ / ที่มีการป้องกันคุณสมบัติฟิลด์และอื่น ๆ ของคลาส Super จะกลายเป็นส่วนหนึ่งของคลาสย่อยซึ่งสามารถแทนที่ได้หากจำเป็น

อะไรที่เทียบเท่ากับสิ่งนั้นใน Javascript?





วิธี Crockford นั้นยังใช้งานได้หรือไม่? ZParenizor.inherits (พาเรนิซอร์);
Loren Shqipognja

ดูเพิ่มเติมที่: JavaScript Extending Class
user56reinstatemonica8

คำตอบ:


80

ตอนนี้ฉันได้เปลี่ยนวิธีทำแล้วฉันพยายามหลีกเลี่ยงการใช้ฟังก์ชันตัวสร้างและ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

jsfiddle

ประโยชน์ที่สำคัญอย่างหนึ่งของการใช้ 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

jsfiddle

นี่คือคำตอบเดิมของฉันจากปี 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"

5
ค่า sub.prototype.constructor เป็นอย่างไร ฉันคิดว่ามันควรจะตั้งค่าย่อยเกินไป
maximus

นอกจากคุณใช้คีย์เวิร์ดที่สงวนไว้ ('super') เป็นชื่อคลาสแล้วฉันไม่สามารถเรียกใช้ตัวอย่างของคุณได้: jsbin.com/ixiyet/8/edit
MOnsDaR

@MOnsDaR ฉันเปลี่ยนชื่อเป็น Base
Bjorn

หากฉันใช้alert()เพื่อดูว่าผลตอบแทนที่ฉันยังคงได้รับinstance.showColor() jsbin.com/uqalin/1undefined
MOnsDaR

1
@MOnsDaR นั่นเป็นเพราะคอนโซลบันทึกจึงไม่ส่งคืนข้อมูลใด ๆ เพื่อให้แสดงการแจ้งเตือน คุณเห็นคำสั่งส่งคืนใน showColor หรือไม่?
Bjorn

191

ใน 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บน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 Crockford

อินสแตนซ์ออบเจ็กต์สืบทอดมาจากอินสแตนซ์ออบเจ็กต์อื่นนั่นแหล่ะ

เทคนิคนี้จะดีกว่าง่าย "เสริมวัตถุ" เพราะคุณสมบัติสืบทอดไม่ได้คัดลอกมาทุกกรณีวัตถุใหม่ตั้งแต่ฐานวัตถุถูกตั้งค่าเป็น[[Prototype]]ของขยายวัตถุในตัวอย่างข้างต้นsubInstanceมีร่างกายเพียงmember3สถานที่ให้บริการ


3
อย่าใช้อินสแตนซ์สำหรับการสืบทอด - ใช้ ES5 Object.create()หรือclone()ฟังก์ชันที่กำหนดเอง(เช่น mercurial.intuxication.org/hg/js-hacks/raw-file/tip/clone.js ) เพื่อสืบทอดโดยตรงจากวัตถุต้นแบบ ดูความคิดเห็นเพื่อ stackoverflow.com/questions/1404559/…สำหรับคำอธิบาย
Christoph

ขอบคุณ @Christoph ฉันกำลังจะพูดถึงObject.createวิธีการ :)
Christian C.Salvadó

1
นี่ไม่ใช่การสืบทอดที่เหมาะสมเนื่องจากคุณจะมีสมาชิกอินสแตนซ์ของ Super ในต้นแบบของ Sub ดังนั้นอินสแตนซ์ของ Sub ทั้งหมดจะแชร์member1ตัวแปรเดียวกันซึ่งไม่เป็นที่ต้องการเลย แน่นอนว่าพวกเขาสามารถเขียนซ้ำได้ แต่นั่นก็ไม่สมเหตุสมผล github.com/dotnetwise/Javascript-FastClassเป็นสารละลายน้ำตาลที่ดีกว่า
Adaptabi

สวัสดี @CMS คุณช่วยอธิบายได้ไหมทำไมฉันต้องสร้างอินสแตนซ์ของคลาสพาเรนต์ในตัวอย่างแรกเพื่อตั้งค่าการสืบทอดสำหรับคลาสย่อย ฉันกำลังพูดถึงบรรทัดนี้: Sub.prototype = new Super();. จะเกิดอะไรขึ้นถ้าทั้งสองคลาสจะไม่ถูกใช้ในระหว่างการเรียกใช้สคริปต์ ดูเหมือนปัญหาด้านประสิทธิภาพ เหตุใดฉันจึงต้องสร้างคลาสหลักหากไม่ได้ใช้คลาสย่อยจริง ช่วยอธิบายให้ละเอียดหน่อยได้ไหม? นี่คือการสาธิตง่ายๆของปัญหา: jsfiddle.net/slavafomin/ZeVL2ขอบคุณ!
Slava Fomin II

ในตัวอย่างทั้งหมดยกเว้นตัวอย่างสุดท้ายมี "คลาส" สำหรับ Super และ "คลาส" สำหรับ Sub จากนั้นคุณจะสร้างอินสแตนซ์ของ Sub คุณสามารถเพิ่มตัวอย่างเทียบเคียงสำหรับตัวอย่าง Object.create ได้หรือไม่?
Luke

50

สำหรับผู้ที่มาถึงหน้านี้ในปี 2019 หรือหลังจากนั้น

ด้วยเวอร์ชันล่าสุดของมาตรฐาน 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()ที่จะเรียกสมาชิกอีกคนหนึ่งใช้ตัวอย่างเช่น

การใช้ชั้นเรียนยังมีอีกมากมาย หากคุณต้องการเจาะลึกเรื่องนี้ขอแนะนำ“ Classes in ECMAScript 6 ” โดย Dr. Axel Rauschmayer *

แหล่งที่มา


1
ภายใต้ฝากระโปรงclassและextendsเป็นน้ำตาลไวยากรณ์ (มีประโยชน์มาก) สำหรับห่วงโซ่ต้นแบบ: stackoverflow.com/a/23877420/895245
Ciro Santilli 郝海东冠状病六四事件法轮功

สำหรับข้อมูลของคุณ 'instance.name' ที่นี่ 'mycar.name' จะส่งคืนชื่อของคลาส นี่เป็นลักษณะการทำงานเริ่มต้นของ ES6 และ ESnext ที่นี่สำหรับ mycar.name จะส่งคืน 'Vehicle'
Shiljo Paulson

7

ใน JavaScript ไม่มี "การสืบทอดคลาส" มีเพียง "การสืบทอดต้นแบบ" ดังนั้นคุณอย่าสร้างคลาส "รถบรรทุก" แล้วทำเครื่องหมายเป็นคลาสย่อยของ "รถยนต์" ให้คุณสร้างวัตถุ "แจ็ค" และบอกว่ามันใช้ "จอห์น" เป็นต้นแบบ ถ้าจอห์นรู้ว่า "4 + 4" นั้นเท่าไหร่แจ็คก็รู้เช่นกัน

ฉันขอแนะนำให้คุณอ่านบทความของ Douglas Crockford เกี่ยวกับการสืบทอดต้นแบบที่นี่: http://javascript.crockford.com/prototypal.htmlนอกจากนี้เขายังแสดงให้เห็นว่าคุณสามารถทำให้ JavaScript มีการสืบทอด "เหมือนกัน" เหมือนในภาษา OO อื่น ๆ ได้อย่างไรจากนั้นจึงอธิบายว่าสิ่งนี้ จริงๆแล้วหมายถึงการทำลาย javaScript ด้วยวิธีที่ไม่ได้ตั้งใจจะใช้


สมมติว่าต้นแบบของแจ็คคือจอห์น ในระหว่างรันไทม์ฉันได้เพิ่มคุณสมบัติ / พฤติกรรมให้กับจอห์น ฉันจะได้รับคุณสมบัติ / พฤติกรรมนั้นจากแจ็คหรือไม่?
Ram Bavireddi

คุณแน่ใจว่าจะ ตัวอย่างเช่นนี่เป็นวิธีที่ผู้คนมักเพิ่มเมธอด "trim ()" ลงในอ็อบเจ็กต์สตริงทั้งหมด (ไม่ใช่ในตัว) ดูตัวอย่างได้ที่นี่: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/ …
naivists

6

ฉันพบว่าคำพูดนี้ให้ความกระจ่างมากที่สุด:

โดยพื้นฐานแล้ว"คลาส" ของ JavaScript เป็นเพียงวัตถุฟังก์ชันที่ทำหน้าที่เป็นตัวสร้างบวกกับวัตถุต้นแบบที่แนบมา ( ที่มา: คุรุแคทซ์ )

ฉันต้องการใช้ก่อสร้างมากกว่าวัตถุดังนั้นฉันบางส่วนกับ "มรดกหลอกคลาสสิก" วิธีการอธิบายไว้ที่นี่โดย 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 เพื่อให้คุณได้ทดลองใช้


4

การสืบทอด Javascript แตกต่างจาก Java และ PHP เล็กน้อยเนื่องจากไม่มีคลาสจริงๆ แต่มีวัตถุต้นแบบที่ให้วิธีการและตัวแปรสมาชิก คุณสามารถโยงต้นแบบเหล่านั้นเพื่อจัดเตรียมการสืบทอดวัตถุ รูปแบบที่พบมากที่สุดที่ผมพบเมื่อค้นคว้าคำถามนี้ได้อธิบายไว้ในMozilla พัฒนาเครือข่าย ฉันได้อัปเดตตัวอย่างเพื่อรวมการโทรไปยังเมธอด superclass และเพื่อแสดงบันทึกในข้อความแจ้งเตือน:

// 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 น่าอึดอัด แต่นี่เป็นเวอร์ชันที่ดีที่สุดที่ฉันพบ


3

คุณทำไม่ได้ (ในแง่คลาสสิก) Javascript เป็นภาษาต้นแบบ คุณจะสังเกตได้ว่าคุณไม่เคยประกาศ "คลาส" ใน Javascript; คุณเป็นเพียงกำหนดสถานะและวิธีการของวัตถุ ในการสร้างมรดกคุณต้องใช้วัตถุบางอย่างและสร้างต้นแบบ ต้นแบบถูกขยายด้วยฟังก์ชันใหม่


1

คุณสามารถใช้.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

1
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

1

หลังจากอ่านหลาย ๆ โพสต์ฉันได้หาวิธีแก้ปัญหานี้ ( jsfiddle ที่นี่ ) ส่วนใหญ่ฉันไม่ต้องการอะไรที่ซับซ้อนกว่านี้

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();

1

ขอบคุณคำตอบของ 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";
        }
    };
})();


1
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();

2
โปรดอย่าเพิ่งโพสต์รหัสอธิบายว่ามันทำอะไรและตอบคำถามได้อย่างไร
Patrick Hund

1

คลาส ES6:

Javascript ไม่มีคลาส คลาสในจาวาสคริปต์เป็นเพียงการสร้างน้ำตาลสังเคราะห์ที่ด้านบนของรูปแบบการสืบทอดต้นแบบที่จาวาสคริปต์ คุณสามารถใช้ JSclassเพื่อบังคับใช้การสืบทอดต้นแบบได้ แต่สิ่งสำคัญคือต้องตระหนักว่าคุณยังคงใช้ฟังก์ชันตัวสร้างภายใต้ประทุน

แนวคิดเหล่านี้ยังใช้เมื่อคุณขยายจากes6'คลาส' โดยใช้คีย์เวิร์ดขยาย นี่เป็นการสร้างลิงก์เพิ่มเติมในห่วงโซ่ต้นแบบ __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 ()

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();


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.