I've looked everywhere and it doesn't seem like there are any questions let alone answers out there regarding this.
I've tried multiple ways and using prototypal inheritance seemed like it would be the best way
function MyWebSocket(url) {
// do other stuff
WebSocket.call(this, url);
}
MyWebSocket.prototype = Object.create(WebSocket.prototype);
MyWebSocket.prototype.constructor = MyWebSocket;
MyWebSocket.prototype.test = function () { alert('hi'); };
I can assign the test function alone just fine but in trying to override the consutructor I get the error "TypeError: Failed to construct 'WebSocket': Please use the 'new' operator, this DOM object constructor cannot be called as a function" from chrome.
I understand that this is not your typical javascript function/object but I would really like a way to override the WebSocket constructor to set in motion other maintenance functions such as a ping interval and yes I can do this individually in the onopen functions but this is something I want to just be global to all WebSockets opened on the site.
Thanks everyone!
Something like the following could work for you:
function MyWebSocket(url) {
this.ws = new WebSocket(url);
}
MyWebSocket.prototype.test = (function() {
// this = MyWebSocket.ws, i.e. a plain WebSocket obj
}).bind(MyWebSocket.ws);
var myWS = new MyWebSocket(url);
myWS.test(); // does something to the underlying websocket
Or alternately, to do something to the underlying websocket, you could not use bind and instead just refer to this.ws when defining the functions on MyWebSocket.prototype.
Related
I am trying to detect when a function is created, preferable through a constructor. Functions are a type of object, right? So it makes sense that when you create a new one, it calls a constructor. Is there a way to override this, for example, something like this
var old = Function.constructor;
Function.constructor = () => {
alert('new function created!');
old();
};
function asdf() {}
var k = new Function();
If this is not possible, is there a way to get all currently defined functions? I am trying to trigger a piece of code on each function run.
You can't detect function creation.
Functions are a type of object, right?
Yes.
So it makes sense that when you create a new one, it calls a constructor.
No. Or - maybe, but that constructor is internal. Just like the construction of objects from array literals, object literals, regex literals, definition of a function directly creates a native object.
Is there a way to override this?
No. You'd need to hook into the JS engine itself for that.
If this is not possible, is there a way to get all currently defined functions?
No. At best, you could try the debugging API of the JS engine and get a heap snapshot, that should contain all function objects.
I am trying to trigger a piece of code on each function run.
Let me guess, that piece of code is a function itself?
Was able to get a semi-working attempt at this. It reads only global functions but it can add code to both the front and beginning of the function. Any tips on how to improve this, as I use classes a lot when I code?
Thanks to Barmar for the idea of looping through window properties, but since you can't access local functions and class functions, this may be the closest way to do this
<script>
function prepend(name) {
console.time(name);
}
function postpend(name) {
console.timeEnd(name);
}
var filter = ['prepend', 'postpend', 'caches'];
function laggyFunction() {
var l = 0;
while (l<1000) {l++}
}
var functions = [];
for (var property in window) {
try {
if (!filter.includes(property)) { // security error on accessing cache in stackoverflow editor along with maximum call stack size exceeded if prepend and postpend are included
if (typeof window[property] === 'function') {
window[property].original = window[property];
window[property].name = property;
window[property] = function() {
prepend(this.name);
console.log(this.original);
this.original.apply(null, arguments);
postpend(this.name);
}.bind(window[property]);
functions.push(property);
}
}
} catch(e) {
console.warn(`Couldn't access property: `+property+' | '+e);
}
}
document.write(functions); // functions the prepend and postpend are applied to
laggyFunction(); // test performance of the function
</script>
I just want to confirm that I'm not missing something with regards to managing context and overriding methods. I'm using the http-proxy module in a node.js app and I need to override the function HttpProxy.prototype.proxyRequest. I'd like to do it without modifying the original module code directly but haven't been able to find a way to do it.
If I do this:
var httpProxy = require('http-proxy'),
httpProxyOverride = require('./http-proxy-override.js');
httpProxy.HttpProxy.prototype.proxyRequest = httpProxyOverride.proxyRequestOverride;
Then I lose the original context and errors are thrown. If I use apply(), I can provide a new context, but it doesn't appear I can persist the original context.
Based off of this SO thread:
Is it possible to call function.apply without changing the context?
It doesn't appear that there is a way to achieve what I'm trying to do and I'm hoping that someone can confirm this or correct me if I'm wrong.
What about saving the old function and then overwriting it like:
var old = httpProxy.HttpProxy.prototype.proxyRequest;
httpProxy.HttpProxy.prototype.proxyRequest = function () {
old.apply(this, arguments);
//do more stuff
}
taken from Javascript: Extend a Function
Please bear with me as I'm new to JS and am having trouble implementing some things with Meteor. I implemented a class in JavaScript using
function Class() {
this.property = 0
this.method = function () {
return "method called"
}
}
I made a new Meteor Collection bu using new Meteor.collection and successfully retrieved the data on the client and can display Class.property in the html template. However, I am unable to access Class.method and was wondering if there's any way to make this happen and if using Meteor.methods to define functions that take the Class instance as input is the best way to go.
For anyone still looking at this, the reason the code doesn't work is because mongodb stores documents as bson. bson, just like json, does not support functions (http://bsonspec.org) so when the above class is saved by meteor into mongo, the method is not saved as part of the document.
There is no easy elegant solution I'm aware of. I have the same issue. In order to utilise the class method you would need to instantiate the class each time you needed it, which you could implement as part of a database model.
This is not really an answer but in meteor's package manager you can add libraries like backbone.js which gives you models, collection and views and a nice router which I find very handy when making meteor apps. Backbone works well with jQuery.
My other suggestion is using a library like Mootools which unlike jQuery doesn't try to change the way you write javascript but enhancing the experience of making object oriented javascript. (see: jqueryvsmootools). With mootools you can can make a class the following way...
var MyClass = new Class({
'Implements': [Options],
//default options
'options': {
'foo': null
},
'initialize': function(options) {
this.foo = options.foo;
},
'bar' : function() {
return this.foo;
}
});
var blub = new MyClass({'foo': 'Hello World'});
blub.bar(); // "Hello World"
I was looking to do the same thing.
I found a function called "transform" that is called when getting something from a meteor collection. You can use it to add a function to a meteor object just as you require.
Here is an example of adding an "endDate" function and "remaining" functions to a meteor object
Products = new Meteor.Collection("Products", {
transform: function (doc) {
doc.endDate = function () {
// SugarJS gives us minutesAfter() which gives us a nice syntax for
// creating new Date objects
// http://sugarjs.com/api/Number/unitAfter
return ((25).minutesAfter(this.startDate));
};
doc.remaining = function () {
return this.endDate().getTime() - Date.now();
};
return doc;
}
});
Read more here:
http://www.okgrow.com/posts/2014/05/19/meteor-transform/
This approach worked beautifully for me:
http://www.okgrow.com/posts/2014/05/19/meteor-transform/
I don't know anything about Meteor, but I see a problem with your code. You're missing a semi-colon after:
this.property = 0
Without that semi-colon, the javascript interpreter will not execute the this.method assignment.
As an siginificantly simplified scenario, say I have 2 Javascript objects defined as below:
var ClassA = Class.extend({
'say': function(message) {
console.log(message);
}
... // some more methods ...
});
var ClassB = Class.extend({
init: function(obj) {
this._target = obj;
}
});
I'd suppose that in Javascript there is some kind of mechanism could enable us to do the following trick:
var b = new ClassB( new ClassA() );
b.say("hello");
I'd like to find a way to detect if there is a method called upon ClassB, and the method is not defined in ClassB, then I can automatically forward the method call to be upon ClassA, which is a member variable in ClassB.
In a realworld scenario, ClassA is an object implemented as brwoser plugin and inserted into the webpage using <object> tag. It's method is implemented in C++ code so there is no way I can tell its methods from its prototype and insert it to ClassB's prototype beforehand.
I'd like to use the technical to create a native Javascript object, with a narraw-ed version of ClassA's interface. Is there a way I can do this?
I don't think there is a quick cross-browser solution to this.
If you only need Firefox, then use __noSuchMethod__
See here: is-there-such-a-thing-as-a-catch-all-key-for-a-javascript-object
and here: javascript-getter-for-all-properties
Otherwise, I would try something like this:
var b = new ClassB( new ClassA() );
// functionToCall is a string containing the function name
function callOnB(functionToCall) {
if(typeof b[functionToCall] === function) {
b[functionToCall]();
} else {
b._target[functionToCall](); // otherwise, try calling on A
}
}
This is using the Square Bracket Notation where
b.say('hello')
is the same as
b['say']('hello')
Of course, you should probably expand this to take arguments in:
function callOnB(functionToCall, listOfArguments) {...}
Thanks to jfrej's hint on noSunchMethod, I did some more research on it and it turns out what I need is quit fit with Harmony Proxies(here and here). And an example can be found at http://jsbin.com/ucupe4/edit#source
Another related post: http://dailyjs.com/2010/03/12/nosuchmethod/
I am using prototypal inheritance in JavaScript and have hit an issue I can't quite figure out. Many JS inheritance examples show accessing a super's members from a sub, but I need to access the sub's members from the super.
I'm building a tool to performance test mapping web services. I want to support multiple versions of the WMS protocol. I want to keep all shared functionality / properties in a WMS base class wherever possible, and only provide specific version implementation details where necessary. My WMS v1.1.1 function looks like this:
function wms111() {
this.version = '1.1.1';
}
wms111.prototype = new wms();
My wms function (short version) is as follows:
function wms() {
var that = this;
this.HTTPMethod = 'GET';
this.descriptionParameters = {
service: 'wms',
version: that.version,
request: 'getcapabilities'
};
}
I then test this with a call like
var service = new wms111();
var descriptionParameters = service.descriptionParameters;
I get the descriptionParameters object with the service and request properties correctly defined, but version is undefined.
Can anyone help me figure out how I access the correct properties from wms111?
Any help much appreciated.
This should make it work as intended:
function wms111() {
this.descriptionParameters.version = '1.1.1';
}
Instead of defining a brand new property, just overwrite the property that should be different in the child.
Here it is in action: http://jsfiddle.net/Wd9vE/1/
I could be wrong on this one, but I'm pretty sure you can't. Inheritance works top-down, not bottom-up. You can overload the function in the subclass, but that's essentially treating that function in the superclass as an abstract function, which has to be overloaded.