Làm thế nào để kế thừa từ một lớp trong javascript?


99

Trong PHP / Java người ta có thể làm:

class Sub extends Base
{
}

Và tự động tất cả các phương thức công khai / bảo vệ, thuộc tính, trường, v.v. của Super class trở thành một phần của Sub class có thể được ghi đè nếu cần.

Tương đương với điều đó trong Javascript là gì?





Cách crockford đó vẫn hoạt động chứ? ZParenizor.inherits (Parenizor);
Loren Shqipognja

Câu trả lời:


80

Tôi đã thay đổi cách thực hiện việc này ngay bây giờ, tôi cố gắng tránh sử dụng các hàm khởi tạo và thuộc tính của chúng prototype, nhưng câu trả lời cũ của tôi từ năm 2010 vẫn ở dưới cùng. Bây giờ tôi thích hơn Object.create(). Object.createcó sẵn trong tất cả các trình duyệt hiện đại.

Tôi nên lưu ý rằng Object.createnó thường chậm hơn nhiều so với việc sử dụng newvới một hàm tạo hàm.

//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

Một trong những lợi ích lớn của việc sử dụng Object.create là có thể chuyển đối số defineProperties , đối số này cung cấp cho bạn quyền kiểm soát đáng kể đối với cách các thuộc tính trên lớp có thể được truy cập và liệt kê, và tôi cũng sử dụng các hàm để tạo các phiên bản, chúng phục vụ như theo một cách nào đó, bạn có thể thực hiện khởi tạo ở cuối thay vì chỉ trả về cá thể.

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

Đây là câu trả lời ban đầu của tôi từ năm 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
Làm thế nào về giá trị sub.prototype.constructor? Tôi nghĩ rằng nó cũng nên được đặt thành giá trị phụ.
maximus

Bên cạnh đó bạn đang sử dụng các từ khóa dành riêng ( 'siêu') như classnames, tôi đã không thể có được ví dụ bạn chạy: jsbin.com/ixiyet/8/edit
MOnsDaR

@MOnsDaR Tôi đã đổi tên nó thành Base
Bjorn

Nếu tôi sử dụng alert()để xem những gì instance.showColor()tôi vẫn nhận được trả lại undefined. jsbin.com/uqalin/1
MOnsDaR

1
@MOnsDaR đó là bởi vì bảng điều khiển ghi nhật ký, nó không trả lại bất kỳ thứ gì để cảnh báo hiển thị. Bạn có thấy câu lệnh trả về trong showColor không?
Bjorn

190

Trong JavaScript, bạn không có các lớp nhưng bạn có thể nhận thừa kế và tái sử dụng hành vi theo nhiều cách:

Kế thừa giả cổ điển (thông qua tạo mẫu):

function Super () {
  this.member1 = 'superMember1';
}
Super.prototype.member2 = 'superMember2';

function Sub() {
  this.member3 = 'subMember3';
  //...
}
Sub.prototype = new Super();

Nên sử dụng với newtoán tử:

var subInstance = new Sub();

Ứng dụng hàm hoặc "chuỗi hàm tạo":

function Super () {
  this.member1 = 'superMember1';
  this.member2 = 'superMember2';
}


function Sub() {
  Super.apply(this, arguments);
  this.member3 = 'subMember3';
}

Cách tiếp cận này cũng nên được sử dụng với newtoán tử:

var subInstance = new Sub();

Sự khác biệt với ví dụ đầu tiên là khi chúng ta applyphương thức Superkhởi tạo cho thisđối tượng bên trong Sub, nó sẽ thêm các thuộc tính được gán cho thison Super, trực tiếp trên thể hiện mới, ví dụ: subInstancechứa các thuộc tính member1member2trực tiếp ( subInstance.hasOwnProperty('member1') == true;).

Trong ví dụ đầu tiên, những thuộc tính đó được tiếp cận thông qua chuỗi nguyên mẫu , chúng tồn tại trên một [[Prototype]]đối tượng bên trong .

Thừa kế ký sinh hoặc Cơ cấu tạo nguồn:

function createSuper() {
  var obj = {
    member1: 'superMember1',
    member2: 'superMember2'
  };

  return obj;
}

function createSub() {
  var obj = createSuper();
  obj.member3 = 'subMember3';
  return obj;
}

Cách tiếp cận này về cơ bản dựa trên "đối tượng tăng cường", bạn không cần sử dụng newtoán tử và như bạn có thể thấy, thistừ khóa không liên quan.

var subInstance = createSub();

ECMAScript 5 Ed. Object.createphương pháp:

// 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';

Phương pháp trên là một kỹ thuật kế thừa nguyên mẫu do Crockford đề xuất .

Các thể hiện đối tượng kế thừa từ các thể hiện đối tượng khác, thế là xong.

Kỹ thuật này có thể tốt hơn so với đơn giản "đối tượng tăng thêm" vì tài sản thừa kế không được sao chép trên tất cả các trường hợp đối tượng mới, kể từ khi cơ sở đối tượng được thiết lập như là [[Prototype]]của mở rộng đối tượng, trong ví dụ trên subInstancecó chứa chất chỉ là member3bất động sản.


3
không sử dụng các phiên bản để kế thừa - sử dụng ES5 Object.create()hoặc một clone()chức năng tùy chỉnh (ví dụ: thương mại điện tử.intuxication.org/hg/js-hacks/raw-file/tip/clone.js ) để kế thừa trực tiếp từ đối tượng nguyên mẫu; xem các nhận xét trên stackoverflow.com/questions/1404559/… để có lời giải thích
Christoph

Cảm ơn @Christoph, tôi sắp đề cập đến Object.createphương pháp :)
CMS

1
Đây không phải là kế thừa thích hợp, vì bạn sẽ có các thành viên cá thể của Super trên nguyên mẫu của Sub. Do đó, tất cả các phiên bản của Sub sẽ chia sẻ cùng một member1biến, điều này không mong muốn chút nào. Tất nhiên họ có thể viết lại nó, nhưng điều đó không có ý nghĩa. github.com/dotnetwise/Javascript-FastClass là một giải pháp đường tốt hơn.
Adaptabi

Xin chào @CMS, bạn có thể giải thích giúp tôi tại sao tôi cần tạo phiên bản của lớp cha trong ví dụ đầu tiên để thiết lập kế thừa cho lớp con không? Tôi đang nói về dòng này: Sub.prototype = new Super();. Điều gì sẽ xảy ra nếu cả hai lớp sẽ không bao giờ được sử dụng trong quá trình thực thi tập lệnh? Có vẻ như vấn đề về hiệu suất. Tại sao tôi cần tạo lớp cha nếu lớp con không thực sự được sử dụng? Bạn có thể giải thích thêm được không? Đây là minh chứng đơn giản của vấn đề: jsfiddle.net/slavafomin/ZeVL2 Cảm ơn!
Slava Fomin II

Trong tất cả các ví dụ - ngoại trừ ví dụ cuối cùng - có một "lớp" cho Super và một "lớp" cho Sub, sau đó bạn tạo một thể hiện của Sub. Bạn có thể thêm một ví dụ có thể so sánh cho ví dụ Object.create không?
Luke

49

Đối với những người truy cập trang này vào năm 2019 hoặc sau đó

Với phiên bản mới nhất của tiêu chuẩn ECMAScript (ES6) , bạn có thể sử dụng từ khóa class.

Lưu ý rằng định nghĩa lớp không phải là định nghĩa object; do đó không có dấu phẩy giữa các thành viên trong lớp. Để tạo một thể hiện của một lớp, bạn phải sử dụng newtừ khóa. Để kế thừa từ một lớp cơ sở, hãy sử dụng 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'

Để kế thừa từ một lớp cơ sở, hãy sử dụng 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

Từ lớp dẫn xuất, bạn có thể sử dụng super từ bất kỳ hàm tạo hoặc phương thức nào để truy cập lớp cơ sở của nó:

  • Để gọi hàm tạo mẹ, hãy sử dụng super().
  • Để gọi cho một thành viên khác, hãy sử dụng, chẳng hạn như super.getName().

Có nhiều thứ hơn để sử dụng các lớp học. Nếu bạn muốn tìm hiểu sâu hơn về chủ đề này, tôi giới thiệu “ Các lớp học trong ECMAScript 6 ” của Tiến sĩ Axel Rauschmayer. *

nguồn


1
Dưới mui xe, classextendslà đường cú pháp (cực kỳ hữu ích) cho chuỗi nguyên mẫu: stackoverflow.com/a/23877420/895245
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

chỉ cho thông tin của bạn 'instance.name' ở đây 'mycar.name' sẽ trả về tên của lớp. Đây là một hành vi mặc định của ES6 và ESnext. Ở đây cho mycar.name sẽ trả về 'Xe'
Shiljo Paulson

7

Vâng, trong JavaScript không có "kế thừa lớp", chỉ có "kế thừa nguyên mẫu". Vì vậy, bạn không tạo một lớp "xe tải" và sau đó đánh dấu nó là một lớp con của "ô tô". Thay vào đó, bạn tạo một đối tượng "Jack" và nói rằng nó sử dụng "John" làm nguyên mẫu. Nếu John biết, "4 + 4" là bao nhiêu, thì Jack cũng biết.

Tôi khuyên bạn nên đọc bài viết của Douglas Crockford về kế thừa nguyên mẫu tại đây: http://javascript.crockford.com/prototypal.html Anh ấy cũng chỉ ra cách bạn có thể làm cho JavaScript có thừa kế "trông giống nhau" như trong các ngôn ngữ OO khác và sau đó giải thích rằng điều này thực sự có nghĩa là phá vỡ javaScript theo cách mà nó không được sử dụng.


Giả sử nguyên mẫu của Jack là John. Trong thời gian chạy, tôi đã thêm thuộc tính / hành vi vào John. Tôi có nhận được tài sản / hành vi đó từ Jack không?
Ram Bavireddi

Bạn chắc chắn sẽ làm được. Ví dụ: đây là cách mọi người thường thêm phương thức "trim ()" vào tất cả các đối tượng chuỗi (nó không được tích hợp sẵn) Xem ví dụ tại đây: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/ …
naivists

6

Tôi thấy câu trích dẫn này là thú vị nhất:

Về bản chất, một "lớp" JavaScript chỉ là một đối tượng Hàm đóng vai trò như một phương thức khởi tạo cộng với một đối tượng nguyên mẫu được đính kèm. ( Nguồn: Guru Katz )

Tôi thích sử dụng các hàm tạo hơn là các đối tượng, vì vậy tôi thích phương pháp "kế thừa giả cổ điển" được CMS mô tả ở đây . Đây là một ví dụ về đa kế thừa với chuỗi nguyên mẫu :

// 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

Đây là một tài nguyên tốt khác từ MDN và đây là một jsfiddle để bạn có thể dùng thử .


4

Kế thừa Javascript hơi khác một chút so với Java và PHP, vì nó không thực sự có các lớp. Thay vào đó nó có các đối tượng nguyên mẫu cung cấp các phương thức và biến thành viên. Bạn có thể xâu chuỗi các nguyên mẫu đó để cung cấp tính kế thừa đối tượng. Mẫu phổ biến nhất mà tôi tìm thấy khi nghiên cứu câu hỏi này được mô tả trên Mạng nhà phát triển Mozilla . Tôi đã cập nhật ví dụ của họ để bao gồm một cuộc gọi đến một phương thức siêu lớp và hiển thị nhật ký trong một thông báo cảnh báo:

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

Cá nhân tôi thấy tính kế thừa trong Javascript khó xử, nhưng đây là phiên bản tốt nhất mà tôi tìm thấy.


3

bạn không thể (theo nghĩa cổ điển). Javascript là một ngôn ngữ nguyên mẫu. Bạn sẽ thấy rằng bạn không bao giờ khai báo một "lớp" trong Javascript; bạn chỉ đơn thuần xác định trạng thái và phương thức của một đối tượng. Để tạo ra sự kế thừa, bạn lấy một số đối tượng và tạo nguyên mẫu cho nó. Nguyên mẫu được mở rộng với chức năng mới.


1

Bạn có thể sử dụng .inheritWith.fastClass thư viện . Nó nhanh hơn hầu hết các thư viện phổ biến và đôi khi còn nhanh hơn cả phiên bản gốc.

Rất dễ sử dụng:

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
      }
}

Sử dụng

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

Sau khi đọc nhiều bài viết, tôi đã nghĩ ra giải pháp này ( jsfiddle đây ). Hầu hết thời gian tôi không cần một cái gì đó phức tạp hơn

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

Nhờ câu trả lời của CMS và sau khi tìm hiểu một thời gian với nguyên mẫu và Object.create và những gì không, tôi đã có thể đưa ra một giải pháp gọn gàng cho kế thừa của mình bằng cách sử dụng ứng dụng như được hiển thị ở đây:

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
Vui lòng không chỉ đăng mã, hãy giải thích những gì nó làm và cách nó trả lời câu hỏi.
Patrick Hund

1

Các lớp ES6:

Javascript không có các lớp. Các lớp trong javascript chỉ là một đường cú pháp được xây dựng dựa trên mô hình kế thừa nguyên mẫu mà javascript. Bạn có thể sử dụng JS classđể thực thi kế thừa nguyên mẫu nhưng điều quan trọng là phải nhận ra rằng bạn thực sự vẫn đang sử dụng các hàm khởi tạo bên dưới.

Những khái niệm này cũng áp dụng khi bạn mở rộng từ es6'lớp' bằng từ khóa expand. Điều này chỉ tạo ra một liên kết bổ sung trong chuỗi nguyên mẫu. Các__proto__

Thí dụ:

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()cũng là một cách để tạo kế thừa trong JS trong javascript. Object.create()là một hàm tạo một đối tượng mới, lấy một đối tượng hiện có làm đối số. Nó sẽ gán đối tượng đã được nhận làm đối số cho thuộc __proto__tính của đối tượng mới được tạo. Một lần nữa, điều quan trọng là phải nhận ra rằng chúng ta đang bị ràng buộc với mô hình kế thừa nguyên mẫu mà JS thể hiện.

Thí dụ:

const Dog = {
  fluffy: true,
  bark: () => {
      console.log('woof im a relatively cute dog or something else??');
  }
};

const dog = Object.create(Dog);

dog.bark();


0

Bạn không thể kế thừa từ một lớp trong JavaScript, vì không có lớp nào trong JavaScript.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.