Is it possible to give javascript partial class behavior like C# or monkey patching like Ruby does?

和自甴很熟 提交于 2019-12-21 03:02:46

问题


The idea behind partial classes is that you can group certain functions together. The best example of this in C# is putting control definitions in one file and the event handlers in another. In Ruby, you can use Monkey patching to replace entire functions etc to get code to do something you want it to.

I haven't found a reason to do this yet, but I figure as web improves, more of an application is going to be on the client side so I'm wondering if some of the great features I find in server-side languages, I can also use in Javascript.

Does anyone know?


回答1:


// file 1

function augment() {
    this.monkey = "monkey";
}

// file 2

function augmentMore() {
    this.patch = "patch";
}

// file 3

var o = {};
augment.call(o);
augmentMore.call(o);
console.log(o.monkey + o.patch);

Monkey patching works. partial classes can work by convention. For example consider this convention.

// file main
function SomeObject() {
    for (var i = 0, ii = SomeObject.Partial.length; i < ii; i++) {
         SomeObject.Partial[i].apply(this, arguments);
    }
}

SomeObject.Partial.SomeName = function() {
   ...
}

// file extra
SomeObject.Partial.SomeOtherName = function() {
   ...
}

JavaScript is surprisingly powerful. Was there a specific example you were looking for?




回答2:


If such a split makes real sense then you can do this:

File #1

function MyObjectType() { this.init(); }

File #2

MyObjectType.prototype.init = function() { this.one = 1; }

File #3

MyObjectType.prototype.onClick = function() { if(this.one == 1) alert("I am so alone..."); }

And somewhere else you can use it as:

var myObject = new MyObjectType();
myObject.onClick();

Welcome to prototype yet kinda functional programming world!




回答3:


I'm expanding upon Raynos' partial classes example. The following is tested and works:

//  In Car.js
function Car(domelement, wheels, engine, color) {
    this.domelem = domelement;

    //  Wire in partial classes from other files
    for(var i = 0, ii = Car.Partial.length; i < ii; i++) {
         Car.Partial[i].apply(this, arguments);
    }
}
Car.Partial = [];  //  Prepare for declaration of additional partial classes

//  In Car.Events.js
Car.Partial[0] = function Events() {
    //  Create some events on Car with jQuery
    $(this.domelem).click(function() { alert('Car clicked.'); });
}

You can then use a build tool to combine the files into a single script, or you can simply reference the files in order:

<script src="Car.js"></script>
<script src="Car.Events.js"></script>
<script>
    //  Turn first paragraph into our Car object
    var myCar = new Car($('p').get(0));
</script>



回答4:


Here is one approach using ES6 and compatible with ES5 using Babel:

In this example I create a MyClass in several files, using three files:

index.js (this is important so you can import the class just via the folder name)

symbols.js (this contains the symbols for private members)

additionalMethods.js (a file that is later attached to the class prototype)

index.js content

import symbols from "./symbols";

export default class MyClass {
  [symbols.existentPrivateMethod]() {
    return "this is the result";
  }
}

import additionalMethod, {anotherAdditionalMethod, additionalPrivateMethod} from "./additionalMethods";
const additionalMethodsObject = {
  additionalMethod: additionalMethod,
  anotherAdditionalMethod: anotherAdditionalMethod
};
additionalMethodsObject[symbols.additionalPrivateMethod] = additionalPrivateMethod;

Object.assign(MyClass.prototype, additionalMethodsObject);

additionalMethods.js contents

import symbols from "./symbols";

export default function additionalMethod() {
  return this[symbols.existentPrivateMethod]();
}

export function anotherAdditionalMethod() {
  return this[symbols.additionalPrivateMethod]();
}

export function additionalPrivateMethod() {
  return "yet another result";
}

symbols.js content

const symbols = {
  existentPrivateMethod: Symbol("myPrivateMethod"),
  additionalPrivateMethod: Symbol("additionalPrivateMethod")
};

export default symbols;

Complete project https://github.com/nicosommi/partialClass

Complete explanation https://nicosommi.com/2015/08/10/partial-class-approach-for-es6/




回答5:


Redefine the type through inheritance approach like this:

var Dog = Class.extend({
    init:function(data){
         data = data || {};
         this.name = data.name;
    },
    run:function(){ 
        /*impl*/
    }
});

/*other js file that require first file */
var Dog = Dog.extend({
   init:function(data){ 
       this._super(data); 
   },
   bark:function(){ 
       return 'woof';
   }
});

The only problem in this approach is the dependency management, but it works.

obs: using John Resing class.js, but could be written in typescript, ES6, AngularJs, ... and many other libraries.



来源:https://stackoverflow.com/questions/5998944/is-it-possible-to-give-javascript-partial-class-behavior-like-c-sharp-or-monkey

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!