Create subclass of NodeJS Buffer - node.js

I'm trying to create a subclass of NodeJS's buffer. I tried the following:
const SubClass = Object.create(Buffer)
SubClass.prototype.isZero = function () {
for(const value of this.buffer) { // Fails on this line
...
}
}
Then I do the following
SubClass.from([0, 0]).isZero()
It throws
TypeError: undefined is not a function
But this.buffer is defined. So whats the problem (maybe an iterator problem?)? Am I doing something wrong with extending the buffer?

The Buffer isn't a class to extend as you're expecting - it's worthwhile to read the modules function which you are having problems with:
https://github.com/nodejs/node/blob/master/lib/buffer.js#L172
Extending the Buffer class will duplicate all the methods which initialise new instances of Buffer instead of your new SubClass. So you won't be able to extend the buffer class for your defined behaviour. Alternatively, you can wrap it with a class to create a similar interface.
class MyBuffer {
constructor(arg) {
this.buffer = Buffer.from(arg)
}
static from(arg) {
return new MyBuffer(arg);
}
isZero() {
for(const value of this.buffer) {
// Fails on this line
console.log(value)
}
}
}
Then using your preferred syntax:
MyBuffer.from([0, 0]).isZero()

Related

Typescript object property incorrect type

I'm trying to write a simple Discord bot in TypeScript, using discord.js and clime.
I'm running into an issue where I'm trying to access an object property of a context object that I pass around, but it's always null. When I check the properties using either vscode's debugger or console.log, the object seems to have all of the properties that I would expect, except they're all nested one layer too deep.
export class DiscordCommandContext extends Context {
public message:Message;
public client:Client;
constructor (options:ContextOptions, message:Message, client:Client) {
super(options);
this.message = message;
this.client = client;
}
}
When I try accessing it the message property, it's always falsy (if block is skipped over).
if (context.message.guild) {
var settings = await repo.getRealmSettings(+context.message.guild.id);
if (key) {
embed.fields.push({name:key,value:settings[key]});
} else {
Object.keys(settings).forEach(property => {
embed.fields.push({name:property,value:settings[property]});
});
}
}
But in the console, I see this:
DiscordCommandContext appears to have nested "message" objects, one of the wrong type
I cannot access context.message.message, I get "Property 'message' does not exist on type 'Message'", which is as I would expect.
EDIT 1
My instantiation code looked like this:
var options:ContextOptions = {
commands: argArr,
cwd: ""
};
var context = new DiscordCommandContext(options, this.message, this.client );
Where argArr is a split string passed into the method and both this.message and this.client are populated in the constructor of the calling class (none are null)
I managed to get DiscordCommandContext to function properly by changing it to this:
export class DiscordCommandContext extends Context {
public message:Message;
public client:Client;
public realmSettings: RealmSettings;
constructor (options:ContextOptions, contextExtension:DiscordCommandContextValues) {
super(options);
this.message = contextExtension.message;
this.client = contextExtension.client;
this.realmSettings = contextExtension.realmSettings
}
}
export interface DiscordCommandContextValues {
message:Message;
client:Client;
realmSettings: RealmSettings;
}
And calling it like this:
var context = new DiscordCommandContext(options, {message:this.message, client:this.client, realmSettings: settings} );
I'm not sure if that's the right way or not... but it works.

Can I overload method in module.export in node.js?

I have an app.js with this code:
var addnote = (title,body) => { /* enter code here */ }
module.exports = {addnote};
Can I add another addnotes function with different parameters to that file?
Function overloading in JavaScript does not exist like in other programming languages such as C# and Java.
What you should be looking to do is pass an object as a parameter that has properties attached and filter them out there..
You could call different functions from your little 'mapping function' just implement the logic there if it isn't big (to keep the code clear).
function foo(parameters){
var title = parameters.title;
var body = parameters.body;
if(parameters.extraProperty){
// oh we have extraProperty passed in too, run a different function?
bar(title, body, parameters.extraProperty); // ??
}
}
foo({title: 'Title', body: 'Body', extraProperty: 'This is extra...'});
If this is your own custom module, you can use the concept of function overriding, where each child class can have its own way to handle something and also have a default way to do things.
class Parent {
constructor(name) {
this.name = name;
}
greet() {
console.log(`Hello ${this.name}`);
}
}
class Child1 extends Parent {
constructor(name) {
super(name);
}
greet() {
console.log(`Hey there ${this.name}. This is Child 1`);
}
}
class Child2 extends Parent {
constructor(name) {
super(name);
}
greet() {
console.log(`Hi there ${this.name}. This is Child 2`);
}
}
const o1 = new Child1('Foo')
const o2 = new Child2('Foo')
o1.greet();
o2.greet();
But if you are trying to override a function in an external module(You do not have access to that code, like a library), my suggestion is to create a wrapper and add functionality there.

Node.js typerror cannot set property of undefined

I get this error when running my code.
TypeError: Cannot set property 'variableName' of undefined
My Code block is.
static setOnline(stream) {
this.Streams[stream.name] = stream;
this.updateStreams();
}
The line error is this line
this.Streams[stream.name] = stream;
After googling I think its not setting my array properly. Any help would be great!
EDIT:
class Streams {
static setOnline(exampleStreamName) {
this.streams[exampleStreamName.name] = stream;
this.updateStreams();
}
}
exampleStreamName is an external string inside of a .json file.
Static functions do not have a 'this' member. That's what makes them static. This pattern is a 'singleton', as you are using only one instance or class.
class Streams {
static setOnline(exampleStream) {
Streams.streams[exampleStream.name] = exampleStream;
Streams.updateStreams();
}
static updateStreams() {
console.log(Streams.streams);
}
}
Streams.streams = {}
Streams.setOnline({
name: 'foo'
})
Streams.setOnline({
name: 'bar'
})
More musings...
It's more flexible to put the streams object inside the Streams class and create one you use everywhere.
It's also confusing to have a static streams member that is not a Streams instance.

Handle function calls on a class in Node.JS

Assuming that you have a class
class MyClass {
world() {
console.log("hello world");
}
}
I can run the method similar to the following:
var hello = new MyClass();
hello.world();
# outputs: hello world
Is there a way to handle direct function calls on an object? For example:
hello();
Returns: TypeError: hello is not a function.
Can I make this call a default function? For example, similar to PHP's invoke function ...
We can only make something callable in JavaScript if that thing is an object which, at some point, delegates to Function.prototype. Therefore, our class will need to extend Function or extend from a class which extends Function. We also need to be able to access instance variables from our class object (in order to call invoke()), so it needs to be bound to itself. This binding can only happen in the constructor.
Since our class will inherit from Function, we need to call super before being able to use this . However, the Function constructor actually takes a code string, which we won't have, because we want to be able to set invoke later on. So we'll need to extend Function in a different class which will be the parent class to our class and which will do the work of setting the prototype of our dummy function (which we need in order to be able to call the returned object). Bringing all of this together, we get:
class ExtensibleFunction extends Function {
constructor(f) {
// our link to Function is what makes this callable,
// however, we want to be able to access the methods from our class
// so we need to set the prototype to our class's prototype.
return Object.setPrototypeOf(f, new.target.prototype);
}
}
class MyClass extends ExtensibleFunction {
constructor() {
// we build an ExtensibleFunction which accesses
// the late-bound invoke method
super(function() { return this.invoke(); });
return this.bind(this); // and bind our instance
// so we have access to instance values.
}
invoke() {
console.log("Hello, world!");
}
}
x = new MyClass();
x(); //prints "Hello, world!"
I mostly adapted the techniques found in this answer in order to do this.
An interesting aspect of using this technique is that you could name MyClass something like Callable and remove the invoke method - then any class which extends Callable would become callable as long as it had an invoke() method. In fact...
class ExtensibleFunction extends Function {
constructor(f) {
// our link to Function is what makes this callable,
// however, we want to be able to access the methods from our class
// so we need to set the prototype to our class's prototype.
return Object.setPrototypeOf(f, new.target.prototype);
}
}
class Callable extends ExtensibleFunction {
constructor() {
// we build an ExtensibleFunction which accesses
// the late-bound invoke method
super(function() { return this.invoke(); });
return this.bind(this); // and bind our instance
// so we have access to instance values.
}
}
class CallableHello extends Callable {
invoke() {
console.log("Hello, world!");
}
}
class CallableBye extends Callable {
invoke() {
console.log("Goodbye cruel world!");
}
}
x = new CallableHello();
x(); //prints "Hello, world!"
y = new CallableBye();
y(); //prints "Goodbye cruel world!"
(Of course, you could get the same effect by setting properties on function objects, but this is more consistent I guess)

How do I access JavaScript this from ScriptSharp?

I'm trying to do the following.
var handler = e => { handle(); item.Unbind("event", this); }
item.Bind("event", handler);
In JavaScript this would properly work, but ScriptSharp replaces JavaScript's this with reference to the instance of class containing method with that code. How do I avoid this behavior and get a reference to the lambda from the lambda itself?
Here's how you could do it (assuming Bind takes a delegate with the signature of an Action):
SomeObject item = ...;
Action handler = null;
handler = delegate() {
// do something ... eg. call Handle();
item.Unbind("event", handler);
};
item.Bind("event", handler);
Also, see this question: How to write a function in script# to be called with any object as this, not just with the instance of the class in which it is defined? for a technique for writing code that generates a "this" reference in script.

Resources