我在使对象延伸工作时迷失了方向。我已经阅读了几十个与此主题相关的网站,但我仍然没有更聪明。似乎每个人都使用它自己的方法来完成这项工作,我也是如此,我试图找到扩展/继承对象的最佳方法。
我也知道有很多框架/插件来涵盖这个功能,但我只是想了解它的工作原理。没有提到大多数这些框架包含许多我可能永远不会使用的其他东西,因此我试图创建自己的东西。
我能够扩展一个对象,在我开始向目标对象添加方法之前,一切似乎都没问题。要了解此问题,请参阅以下示例...
或者只是试试这个JSFiddle
问题是,在初始化Rabbit
对象的新实例后,我无法访问 Rabbit 方法changeName
。
而且我不明白它为什么会发生,也就是说它为什么不认识这种方法。
[*] 请查看我下面的更新代码(也是JFiddle),现在看来一切正常。
如果这是一个好方法或我错过了什么,请告知anoyne吗?
var Class = (function(NewClass){
if(NewClass.length != 0){
var extend = function(target, source, args) {
Object.getOwnPropertyNames(source).forEach(function(propName) {
if(propName !== "Extend")
{
Object.defineProperty(
target, propName,
Object.getOwnPropertyDescriptor(source, propName)
);
}
if (typeof source[propName] !== 'undefined'){
delete source[propName];
}
});
return target;
};
var inherit = function(source, args){
var baseClass = Object.getPrototypeOf(this);
baseClass.prototype = extend.call(this, baseClass, source, args);
};
if(NewClass.Extend){
var Class = function(){ //// New Class Constructor ////
if(typeof NewClass.Extend === 'function'){
NewClass.Extend.apply(this, arguments);
inherit.call(this, NewClass.Extend);
console.log(NewClass)
inherit.call(this, NewClass, arguments);
if(NewClass.Initialize){
NewClass.Initialize.call(this, arguments);
}
}
};
Class.prototype.constructor = Class;
return Class;
}
}
});
var Animal =(function(args){//// constructor ////
var self = this;
self.name = typeof args !== 'undefined' ? args.name : null;
self.bags = 0;
});
var Rabbit = new Class({
Extend: Animal ,
Initialize: function(){
console.log(this.name)
},
changeName: function(a){
console.log(this.name)
}
});
var LittleRabbit = new Rabbit({name: "LittleRabbit", type: "None"});
console.log(LittleRabbit instanceof Rabbit)
console.log(LittleRabbit)
LittleRabbit.changeName("alex");
答案 0 :(得分:2)
您的extend
函数工作错误,因为Object.getPrototypeOf返回原型,所以在更多情况下它 object
var extend = function(source, args){
var baseClass = Object.getPrototypeOf(this);
source.apply(this, args);
//so here you just add property prototype to object, and this not same as set prototype to function.
baseClass.prototype = Object.create(source.prototype);
};
所以你可以在下面的代码片段中解决这个问题:
function Class(args) {
if (arguments.length != 0) {
var C = function() {
if (typeof args.Extend == 'function') {
args.Extend.apply(this, arguments)
}
if (args.Initialize) {
args.Initialize.call(this);
}
};
if (typeof args.Extend == 'function') {
C.prototype = Object.create(args.Extend.prototype);
}
Object.keys(args).filter(function(el) {
return ['Extend', 'Initialize'].indexOf(el) == -1
}).forEach(function(el) {
C.prototype[el] = args[el];
});
return C;
}
};
var Animal = (function(args) { //// constructor ////
var self = this;
self.name = typeof args !== 'undefined' ? args.name : null;
self.bags = 0;
});
var Rabbit = Class({
Extend: Animal,
Initialize: function() {
console.log(this.name);
},
changeName: function(a) {
this.name = a;
}
});
var LittleRabbit = new Rabbit({
name: "LittleRabbit",
type: "None"
});
console.log(LittleRabbit instanceof Rabbit);
console.log(LittleRabbit instanceof Animal);
console.log(LittleRabbit.name);
LittleRabbit.changeName('new little rabbit');
console.log(LittleRabbit.name);

答案 1 :(得分:1)
我建议阅读MDN article detailing the JavaScript object model。它包含“手动”子类化的示例:
function Employee() {
this.name = "";
this.dept = "general";
}
function Manager() {
Employee.call(this);
this.reports = [];
}
Manager.prototype = Object.create(Employee.prototype);
function WorkerBee() {
Employee.call(this);
this.projects = [];
}
WorkerBee.prototype = Object.create(Employee.prototype)
将您的示例翻译为此样式很简单:
function Animal(name) {
this.name = name;
this.bags = 0;
}
function Rabbit(name) {
Animal.call(this, name);
console.log(this.name);
}
Rabbit.prototype = Object.create(Animal.prototype);
Rabbit.prototype.changeName = function(name) {
this.name = name;
};
然后你可以轻松运行你的例子,修改一下:
var LittleRabbit = new Rabbit("LittleRabbit");
console.log(LittleRabbit instanceof Rabbit)
console.log(LittleRabbit)
LittleRabbit.changeName("new name");
一旦你理解了这一点,我建议你不要建立自己的类创建机制,只需使用ES6 classes:
class Animal {
constructor(name) {
this.name = name;
this.bags = 0;
}
}
class Rabbit extends Animal {
constructor(name) {
super(name);
console.log(this.name);
}
changeName(name) {
this.name = name;
}
}
您可以在Babel REPL中看到此示例。某些浏览器/ js运行时natively support ES6 classes already,但您可以使用Babel将代码转换为ES5,以用于尚未安装的环境。
顺便说一下,实际上需要完全正确地进行子类化。一个更完整的例子(可能不适用于所有环境)是:
function Animal() {}
function Rabbit() {
Animal.call(this);
}
Rabbit.prototype = Object.create(Animal.prototype);
Rabbit.prototype.constructor = Rabbit;
Rabbit.__proto__ = Animal;
答案 2 :(得分:0)
可以为ES6类继承一个选项:
'use strict';
class Animal {
constructor( name ) {
this.name = name;
}
changeName( name ) {
this.name = name;
}
}
class Rabbit extends Animal {
constructor() {
super( 'rabbit' );
}
}
let littleRabbit = new Rabbit();
console.log( littleRabbit.name ); //log default name
littleRabbit.changeName( 'littleRabbit' ); //executing an method of animal class
console.log( littleRabbit.name ); //log changed name
你不需要为旧的好javascript制作OOP继承的“开销”,因为那里有“翻译器”将你的es6代码翻译成es5代码。例如,babel:https://babeljs.io/
我认为值得尝试一下......