简体   繁体   English

有趣的JavaScript继承模式

[英]Interesting JavaScript inheritance pattern

I have recently watched a video where Douglas Crockford was explaining inheritance patterns of Javascript. 我最近看了一段视频,其中道格拉斯·克罗克福德Douglas Crockford)正在解释Java的继承模式。 The video itself is pretty old - it was filmed 6 years ago - but still useful. 该视频本身很旧-它是6年前拍摄的-但仍然有用。 In that video he showed one inheritance pattern he kinda invented (although I am not sure who the author is). 在该视频中,他展示了他发明的一种继承模式(尽管我不确定作者是谁)。 This is the code using his approach: 这是使用他的方法的代码:

 // imitation of new operator function objectConstructor(obj, initializer, methods) { // create prototype var func, prototype = Object.create(obj && obj.prototype); // add methods to the prototype if(methods) Object.keys(methods).forEach(function(key) { prototype[key] = methods[key]; }); // function that will create objects with prototype defined above func = function() { var that = Object.create(prototype); if(typeof initializer === 'function') initializer.apply(that, arguments); return that; } func.prototype = prototype; prototype.constructor = func; return func; } var person = objectConstructor(Object, function(name) { this.name = name; }, { showName: function() { console.log(this.name); } }); var employee = objectConstructor(person, function(name, profession) { this.name = name; this.profession = profession; }, { showProfession: function() { console.log(this.profession); } }); var employeeInfo = employee('Mike', 'Driver'); employeeInfo.showName(); // Mike employeeInfo.showProfession(); // Driver 

Unfortanately, he didn't show the invocation. 不幸的是,他没有显示该调用。 So, this part 所以这部分

var employeeInfo = employee('Mike', 'Driver');
employeeInfo.showName();
employeeInfo.showProfession();

is mine. 是我的。 It generally works, but it turns out that I repeat this.name = name; 它通常可以工作,但事实证明,我重复了this.name = name; for both "classes" - person and employee . 对于“类”- personemployee I played around but I didn't manage to make it work properly without that repetition. 我玩了一下,但是没有重复就无法使其正常工作。 Seems I cannot get name because such a property isn't contained in the prototypal chain for employee . 似乎我无法name因为employee原型链中不包含这样的属性。 I didn't succeed either in mixing in stuff like person.call(this, arguments) . 我也没有成功地混入诸如person.call(this, arguments)类的东西。 So, apart from whether it is cool/nice/smart/sensible etc. or not in 2017, how could I remove this.name = name; 因此,除了在2017年是否酷/漂亮/智能/明智等之外,我如何删除this.name = name; from employee and get the same result? employee那里得到相同的结果? Or everything is ok and this approach doesn't suppose it? 还是一切正常,这种方法不可行吗?

Since the func constructor completely disregards this , passing any context to it via call or apply will not work. 由于func 构造函数完全忽略了this ,因此无法通过callapply将任何上下文传递给它。 Creating a way to copy over the super class' properties after creating an object is one of the ways you could accomplish your task. 创建对象后,创建一种复制类属性的方法是您可以完成任务的一种方法。

 // imitation of new operator function objectConstructor(obj, initializer, methods) { // create prototype var func, prototype = Object.create(obj && obj.prototype); // add methods to the prototype if(methods) Object.keys(methods).forEach(function(key) { prototype[key] = methods[key]; }); // function that will create objects with prototype defined above func = function() { var that = Object.create(prototype); if(typeof initializer === 'function') initializer.apply(that, arguments); return that; } func.prototype = prototype; prototype.constructor = func; return func; } function copyProperties(source, target) { for (var prop in source) { if (source.hasOwnProperty(prop)) { target[prop] = source[prop]; } } } var person = objectConstructor(Object, function(name) { this.name = name; }, { showName: function() { console.log(this.name); } }); var employee = objectConstructor(person, function(name, profession) { copyProperties(person.apply(null, arguments), this); this.profession = profession; }, { showProfession: function() { console.log(this.profession); } }); var employeeInfo = employee('Mike', 'Driver'); employeeInfo.showName(); // Mike employeeInfo.showProfession(); // Driver 

Here is your snippet with 2 small modifications so that you can do a super(name) type of call. 这是您的代码段,其中进行了2处小的修改,因此您可以进行super(name)类型的呼叫。

I've placed comments were I've made the modifications.. with prefix keith: 我已经放置了注释,并且进行了修改..使用前缀keith:

 // imitation of new operator function objectConstructor(obj, initializer, methods) { // create prototype var func, prototype = Object.create(obj && obj.prototype); // add methods to the prototype if(methods) Object.keys(methods).forEach(function(key) { prototype[key] = methods[key]; }); // function that will create objects with prototype defined above func = function() { var that = Object.create(prototype); if(typeof initializer === 'function') initializer.apply(that, arguments); return that; } func.prototype = prototype; //keith: store the initialization in constructor, //keith: as func is already creating the object.. prototype.constructor = initializer; return func; } var person = objectConstructor(Object, function(name) { this.name = name; }, { showName: function() { console.log(this.name); } }); var employee = objectConstructor(person, function(name, profession) { //keith: call our super person(name) person.prototype.constructor.call(this, name); this.profession = profession; }, { showProfession: function() { console.log(this.profession); } }); var employeeInfo = employee('Mike', 'Driver'); employeeInfo.showName(); // Mike employeeInfo.showProfession(); // Driver 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM