Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
JavaScript扩展类_Javascript_Oop_Object_Inheritance_Ecmascript 6 - Fatal编程技术网

JavaScript扩展类

JavaScript扩展类,javascript,oop,object,inheritance,ecmascript-6,Javascript,Oop,Object,Inheritance,Ecmascript 6,我有一个基本类: function Monster() { this.health = 100; } Monster.prototype.growl = function() { console.log("Grr!"); } class Monster{ constructor(){ this.health = 100; } growl() { console.log("Grr!");

我有一个基本类:

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

Monster.prototype.growl = function() {
  console.log("Grr!");
}
class Monster{
       constructor(){
             this.health = 100;
        }
       growl() {
           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
}
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
        }

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

下面针对ES6更新

2013年3月和ES5 此MDN文档很好地描述了扩展类:

特别是,他们现在处理的是:

// 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
请注意,某些旧浏览器(包括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设计人员已经听到了我们的请求,并采取了更合适的方法来解决这个问题

在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非常常见,但它是:

试试这个:

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

Monkey.extends(Monster);
function Monkey() {
  Monster.apply(this, arguments); // call super
}
编辑:我在这里放了一个快速演示。请注意,
extends
在JS中是一个保留字,在删除代码时可能会收到警告,您可以简单地将其命名为
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"

如果您不喜欢prototype方法,因为它实际上没有良好的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缩小):

这是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扑克增强了我们的功能原型:

Function.prototype.extend = function(constructor, methods, statics) {
    return defineSubclass(this, constructor, methods, statics);
};
定义Monster类后,我们将执行以下操作(对于我们要扩展/继承的任何新类都是可重用的):


对于传统的扩展,您只需将超类编写为构造函数, 然后将此构造函数应用于继承的类

     function AbstractClass() {
      this.superclass_method = function(message) {
          // do something
        };
     }

     function Child() {
         AbstractClass.apply(this);
         // Now Child will have superclass_method()
     }
angularjs示例:


ES6现在为您提供了使用扩展关键字的机会:

然后,您的代码将是:

您有一个基类:

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

Monster.prototype.growl = function() {
  console.log("Grr!");
}
class Monster{
       constructor(){
             this.health = 100;
        }
       growl() {
           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
}
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
        }

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

我可以提出一个变体,只要在书中读过,它似乎是最简单的:

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
总结: 有多种方法可以解决用Javascript原型扩展构造函数的问题。以下哪种方法是基于意见的“最佳”解决方案。然而,这里有两种常用的方法来扩展构造函数的函数原型

ES 2015课程:
类怪物{
建造师(健康){
这就是健康
}
咆哮(){
console.log(“Grr!”);
}
}
类猴子扩展怪物{
建造师(健康){
super(health)//调用super执行Monster的构造函数
这个。巴纳计数=5;
}
}
恒河猴=新猴(50);
控制台日志(怪物类型);
控制台日志(monkey)绝对最小的(和上面的许多答案不同,也是正确的)版本是:

function Monkey(param){
  this.someProperty = param;
}
Monkey.prototype = Object.create(Monster.prototype);
Monkey.prototype.eatBanana = function(banana){ banana.eat() }

就这些。你可以用这个来阅读,
Monkey
不会继承
Monster
的属性(
health
)。如果调用
Monkey.extends(Monster)
@Phil之前未定义
Monkey
,您还将得到“ReferenceError:Monkey未定义”,这是一个函数声明,它被提升,应该可以工作。这段代码中唯一的“问题”是“extends是一个保留字”,但您可以轻松地将其更改为任何其他标识符。谢谢,伙计。这太棒了。可以在Node.js中应用它来为构造函数等创建基类,所以我不必每次创建构造类时都创建mongo连接等。如果Person构造函数需要参数,例如Person(name)@PhamHuyAnh只需做一些类似于
functionperson(n){this.name=n;}
Student.prototype=newperson()此行将导致错误。
Student.prototype=Object.create(Person.prototype)经典的创建方法在这里工作我正在尝试创建一个扩展函数,它可以自己完成所有的工作。是否可能以某种方式将“Person.call(this);”或下面的示例“Monster.apply(this,arguments);”移动到此类函数?我做这件事有困难。谢谢你给我这个库的链接!!看起来很神奇:D似乎这就是我一直在寻找的东西!这是如此干净,可以确认在chrome 51.0、Firefox 47中工作。使用
try{}catch(e){}
blocks来管理它,如果需要,告诉最终用户更新浏览器。可能重复