我正在寻找一种简单的方法来创建两个类,一个继承自另一个类,子类重新定义父方法之一,并在新方法中调用父类。
例如,有一个类Animal
和Dog
,其中Animal类定义了一个方法makeSound()
,该方法确定了如何输出声音,然后Dog会覆盖它自己的{{1} 1}}制作“低音”声音的方法,但同时也调用动物的makeSound()
输出那个低音。
我查看了John Resig的模型here,但它使用了原生的makeSound()
属性,该属性在ECMA脚本中显然已被折旧5.这是否意味着我不应该使用John Resig的代码?
使用Javascript的原型继承模型编写动物/狗代码的简洁方法是什么?
答案 0 :(得分:27)
这是否意味着我不应该使用John Resig的代码?
正确,而不是在严格模式下使用ES5时。但是,它很容易适应:
/* Simple JavaScript Inheritance for ES 5.1
* based on http://ejohn.org/blog/simple-javascript-inheritance/
* (inspired by base2 and Prototype)
* MIT Licensed.
*/
(function(global) {
"use strict";
var fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/;
// The base Class implementation (does nothing)
function BaseClass(){}
// Create a new Class that inherits from this class
BaseClass.extend = function(props) {
var _super = this.prototype;
// Set up the prototype to inherit from the base class
// (but without running the init constructor)
var proto = Object.create(_super);
// Copy the properties over onto the new prototype
for (var name in props) {
// Check if we're overwriting an existing function
proto[name] = typeof props[name] === "function" &&
typeof _super[name] == "function" && fnTest.test(props[name])
? (function(name, fn){
return function() {
var tmp = this._super;
// Add a new ._super() method that is the same method
// but on the super-class
this._super = _super[name];
// The method only need to be bound temporarily, so we
// remove it when we're done executing
var ret = fn.apply(this, arguments);
this._super = tmp;
return ret;
};
})(name, props[name])
: props[name];
}
// The new constructor
var newClass = typeof proto.init === "function"
? proto.hasOwnProperty("init")
? proto.init // All construction is actually done in the init method
: function SubClass(){ _super.init.apply(this, arguments); }
: function EmptyClass(){};
// Populate our constructed prototype object
newClass.prototype = proto;
// Enforce the constructor to be what we expect
proto.constructor = newClass;
// And make this class extendable
newClass.extend = BaseClass.extend;
return newClass;
};
// export
global.Class = BaseClass;
})(this);
答案 1 :(得分:7)
使用Object.create()+赋值构造函数
的原型链function Shape () {
this.x = 0;
this.y = 0;
}
Shape.prototype.move = function (x, y) {
this.x += x;
this.y += y;
};
function Rectangle () {
Shape.apply(this, arguments); // super constructor w/ Rectangle configs if any
}
Rectangle.prototype = Object.create(Shape.prototype); // inherit Shape functionality
// works like Rectangle.prototype = new Shape() but WITHOUT invoking the constructor
Rectangle.prototype.constructor = Rectangle;
var rect = new Rectangle();
rect instanceof Rectangle && rect instanceof Shape // returns true
的信息
答案 2 :(得分:3)
这是我使用链接进行继承以及允许_super工作的原因。
/**
* JavaScript simple inheritance
* by Alejandro Gonzalez Sole (base on John Resig's simple inheritance script)
* MIT Licensed.
**/
(function (){
var initializing = false,
fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.* /;
function Class(){};
function inheritClass(superClass){
var self = this;
function Class(){
if (!initializing && typeof this._constructor === 'function')
this._constructor.apply(this, arguments);
}
Class.prototype = superClass.prototype;
Class.prototype._constructor = superClass;
Class.prototype.constructor = Class;
Class.extend = extendClass;
//currenlty if you inhert multiple classes it breaks
Class.inherit = inheritClass;
return Class;
};
function extendClass(prop) {
var self = this;
var _super = self.prototype;
function Class(){
if (!initializing && typeof this._constructor === 'function')
this._constructor.apply(this, arguments);
}
initializing = true;
var prototype = new self();
initializing = false;
for (var name in prop) {
prototype[name] = typeof prop[name] == "function" &&
typeof _super[name] == "function" && fnTest.test(prop[name]) ?
(function(name, fn){
return function() {
var tmp = this._super;
this._super = _super[name];
var ret = fn.apply(this, arguments);
this._super = tmp;
return ret;
};
})(name, prop[name]) : prop[name];
}
Class.prototype = prototype;
Class.prototype.constructor = Class;
Class.extend = extendClass;
Class.inherit = inheritClass;
return Class;
};
Class.extend = extendClass;
Class.inherit = inheritClass;
})();
//EXAMPLE
function Person(){
this.name = "No name";
console.log("PERSON CLASS CONSTRUCTOR")
}
Person.prototype.myMethod = function (t){
console.log("MY PERSON", t, this.name);
return -1;
}
var TestPerson = Class.inherit(Person).extend({
_constructor: function(){
this._super();
this.name = "JOhn";
console.log("TEST PERSON CONSTRUCTOR");
},
myMethod: function (t){
console.log("TEST PERSON", t, this.name);
return this._super(t)
}
});
var test = new TestPerson();
console.log(test.myMethod("BA"));
我一直在我的pixi包装上测试它https://github.com/guatedude2/pixijs-cli到目前为止,它对我来说效果很好。
我遇到过这种方法的唯一问题是你只能继承一次。如果再次运行inherit,它将覆盖先前的继承。
答案 3 :(得分:2)
我更喜欢 TypeScript 生成一种继承形式的方式(从下拉列表中选择简单继承)。那个不使用arguments.callee
,而是使用__extends
prototype
。
var __extends = this.__extends || function (d, b) {
function __() { this.constructor = d; }
__.prototype = b.prototype;
d.prototype = new __();
};
var Animal = (function () {
function Animal(name) {
this.name = name;
}
Animal.prototype.move = function (meters) {
alert(this.name + " moved " + meters + "m.");
};
return Animal;
})();
var Snake = (function (_super) {
__extends(Snake, _super);
function Snake(name) {
_super.call(this, name);
}
Snake.prototype.move = function () {
alert("Slithering...");
_super.prototype.move.call(this, 5);
};
return Snake;
})(Animal);
var Horse = (function (_super) {
__extends(Horse, _super);
function Horse(name) {
_super.call(this, name);
}
Horse.prototype.move = function () {
alert("Galloping...");
_super.prototype.move.call(this, 45);
};
return Horse;
})(Animal);
var sam = new Snake("Sammy the Python");
var tom = new Horse("Tommy the Palomino");
sam.move();
tom.move(34);