JavaScript扩展类

Luc*_*ney 71 javascript oop inheritance object ecmascript-6

我有一个基类:

function Monster() {
  this.health = 100;
}

Monster.prototype.growl = function() {
  console.log("Grr!");
}
Run Code Online (Sandbox Code Playgroud)

我想扩展并创建另一个类:

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
}
Run Code Online (Sandbox Code Playgroud)

我做了很多研究,似乎有很多复杂的解决方案在JavaScript中这样做.在JS中实现这一目标的最简单,最可靠的方法是什么?

Oli*_*ryn 137

以下更新了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
Run Code Online (Sandbox Code Playgroud)

请注意,Object.create()在某些旧版浏览器中不支持,包括IE8:

Object.create浏览器支持

如果您需要支持这些,则链接的MDN文档建议使用polyfill,或以下近似值:

function createObject(proto) {
    function ctor() { }
    ctor.prototype = proto;
    return new ctor();
}
Run Code Online (Sandbox Code Playgroud)

使用它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
Run Code Online (Sandbox Code Playgroud)

干净,易懂,就像我们都想要的那样.请记住,尽管ES6很常见,但并不是所有地方都支持它:

ES6浏览器支持

  • 如果Person构造函数需要params,例如Person(name)......? (3认同)
  • @PhamHuyAnh做一些像`function Person(n){this.name = n; }` (2认同)
  • 我正在尝试创建由自己完成所有操作的扩展函数。是否有可能以某种方式移动“Person.call(this);” 或从下面的示例“Monster.apply(this, arguments);” 到这样的功能?我在这样做时遇到了问题。 (2认同)

Abd*_*UMI 15

ES6现在为您提供了使用class&extends关键字的机会:

然后,您的代码将是:

你有一个基类:

class Monster{
       constructor(){
             this.health = 100;
        }
       growl() {
           console.log("Grr!");
       }

}
Run Code Online (Sandbox Code Playgroud)

您想扩展并创建另一个类:

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
        }

}
Run Code Online (Sandbox Code Playgroud)

  • 这是如此清晰,可以确认在Chrome 51.0,Firefox 47中工作. (2认同)

elc*_*nrs 10

试试这个:

Function.prototype.extends = function(parent) {
  this.prototype = Object.create(parent.prototype);
};

Monkey.extends(Monster);
function Monkey() {
  Monster.apply(this, arguments); // call super
}
Run Code Online (Sandbox Code Playgroud)

编辑:我在这里放了一个快速演示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"
Run Code Online (Sandbox Code Playgroud)


Har*_*old 6

如果你不喜欢原型方法,因为它并不是真的以一种漂亮的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;
    }
})
Run Code Online (Sandbox Code Playgroud)

使用轻量级库(2k缩小):https://github.com/haroldiedema/joii