So, I'm new to NodeJS (started learning it two weeks ago) and I decided to delve into the realm of creating my own modules. I looked up some articles and found the best way to create a module with a constructor was the following:
var Foo = function (params) {
//Do constructor stuff
this.params = params;
};
Foo.prototype.test = function () {
console.log(this.params.Message);
};
module.exports = Foo;
Then I would be able do var myFoo = require("./utils/Foo.js")( { Message: "Some Message });
This runs the constructor. However, when I do myFoo.test() I get an error saying Cannot read property 'test' of undefined.
I don't understand why I'm getting the above error. When I add a console.log("Test") to the constructor, I see the log.
Any help would be appreciated.
Methods of the prototype require the use of the new keyword. However when you require it your not using the new keyword.
You have a couple of options. Either put the new keyword in when you require it. (Ive split the two apart by the way as im not entirely sure what will happen with the new keyword if it was new require('module')(). I think it would apply to the require call, not the function call after).
var fooModule = require('./foo.js'),
myFoo = new fooModule('myMessage');
Or you could put that logic in your constructor so it will return a new version if the new keyword is omitted; Your require call would not change but your constructor could be something like:
var Foo = function (params) {
if (!(this instanceof Foo)) {
return new Foo(params);
}
//Do constructor stuff
this.params = params;
};
See fiddle example: https://jsfiddle.net/84ssgare/1/
Generally i would avoid the use of new Keyword anyhow. Its trying to make JavaScript something its not. This article List some good examples of exactly how the new keyword works. It also makes the good point that its a tool and should be used when required, not because its familiar.
You need new to create the object from the constructor:
var foo=require("./utils/Foo.js");
var myFoo = new foo( { Message: "Some Message });
short version:
var myFoo = new require("./utils/Foo.js")( { Message: "Some Message });
In your actual code you are executing a foo function that reruns undefined. And then trying to access undefined as an object with a test property
Related
There is a javascript file with require js framework
init: function(){
var self = this;
self.commonSolutionManager = new solution.CommonSolutionManager();
},
I am creating jasmine test cases for testing the above code . I am creating an object for the above file with this constructor
function solution()
{
CommonSolutionManager = function(){};
}
but it's throwing error "TypeError: solution.CommonSolutionManager is not a constructor"
This block of code places your constructor inside a closure which scopes the constructor to ONLY be accessible with in the closure.
function solution()
{
CommonSolutionManager = function(){};
}
This block of code tries to access the constructor as if it where a property of solution; but it's not, it's more like a private variable with in the solution function.
self.commonSolutionManager = new solution.CommonSolutionManag();
You probably wanted your constructor to be defined in the following way.
// create the solution object and store it in the global namespace
solution = window.solution || {};
// create the constructor
solution.CommonSolutionManag = function() {};
// now you can use the constructor
var csm = new solution.CommonSolutionManag();
NOTE: If you're using requireJS, then this probably isn't the approach you want to take. See RequireJS: How to define a constructor?
You're using solution as an object but it's a function. Not clear on how it should work but the following should fix the problem:
var solution = new function() {
this.CommonSolutionManager = function(){};
}
And you can then use new solution.CommonSolutionManager()
I'm reading a snippet of code that defines a constuctor
var Resource = function(data) {
angular.extend(this, data);
}
and then subsequently defines a method to it.
Resource.query = function(url) {
console.log(url);
}
Can I ask how this works? I know functions are objects as well, and is this the equivalent of the following? But if so, then what happens to the constructor function?
var data = {};
data.query = function(url) {
console.log(url);
}
Also, why wouldn't we simply define it on the prototype instead?
Resource.prototype.query = function(url) {
console.log(url);
}
http://jsfiddle.net/HPg6A/
You would define methods on the prototype only if they are meant to be called on specific instances. When methods are defined directly as constructor members, it's usually to mimic static methods.
Basically, when a method relates very closely to a class, but doesn't make much sense as an instance method, it can be implemented as a static method.
I think that you will agree with me that the second example makes more sense and if you do, you already understood the difference.
1-
var user = new User();
user.findUser('somequery').then(...);
2-
User.findUser('somequery').then(...);
I know functions are objects as well, and is this the equivalent of the following
There's nothing more to what you say. It's just like any other property on any other object.
Also, why wouldn't we simply define it on the prototype instead?
The difference is that each object created using the constructor would then have that method in their prototype chain. This isn't true for properties defined on the constructor itself.
That is:
var Resource = function() {}
Resource.one = function() {
console.log("one");
}
Resource.prototype.two = function() {
console.log("two");
}
var r = new Resource();
r.two(); // => "two"
r.one(); // => TypeError: r.one is not a function
And:
Resource.one(); // => "one"
Resource.two(); // => TypeError: Resource.two is not a function
You might call one a static method, but the language doesn't treat it differently than any other function (unlike methods defined using, say, static in Java).
A factory class isn't the end product I am looking for but it is basically my problem boiled down. I am looking for a class we'll call foo that can be passed in another class bar as a parameter to its constructor such that when later calling fooInstance.create() it returns a new instance of bar. I can easily figure out how to make a fooInstance.create(bar) create an instance of bar. But that isn't what I need. I need each instance of the factory class to create a specific type of object. so:
fooCar = new foo(Car);
fooTruck = new foo(Truck);
myCar = fooCar.create();
myTruck = fooTruck.create();
This would be something easily handled by Generics in c#. I either get errors or I end up screwing with the prototype of foo which then changes the type created by all instances of foo.
Just return a regular object from your factory, with just one create method:
function foo (Constructor) {
return {
create: function () {
return new Constructor();
}
};
}
Check out the fiddle: http://jsfiddle.net/fR5Gz/1/
Thanks to everyone for your help. #missingno I thought the details of what I was trying to do would cloud the issue but now I think it was the other way around. I'll know better for next time. I wasn't looking for type safety but without it maybe there is no reason to do it this way. Maybe I'm stuck in classical thinking.
I actually figured it out myself this morning because I didn't get any email alerts on this thread like I was supposed to so I thought there weren't any replies yet. This is my solution (relevant code only):
ORM.Repository = (function (){
function Repository(ob){
this.construct = ob;
};
//bunch of other generic repository stuff deleted
Repository.prototype.make = function () { return new this.construct();}
return Repository;
})();
Usage:
var carRepository = new ORM.Repository(car);
var personRepository = new ORM.Repository(person);
var myCar = carRepository.make();
var user = personRepository.make();
In Ruby I think you can call a method that hasn't been defined and yet capture the name of the method called and do processing of this method at runtime.
Can Javascript do the same kind of thing ?
method_missing does not fit well with JavaScript for the same reason it does not exist in Python: in both languages, methods are just attributes that happen to be functions; and objects often have public attributes that are not callable. Contrast with Ruby, where the public interface of an object is 100% methods.
What is needed in JavaScript is a hook to catch access to missing attributes, whether they are methods or not. Python has it: see the __getattr__ special method.
The __noSuchMethod__ proposal by Mozilla introduced yet another inconsistency in a language riddled with them.
The way forward for JavaScript is the Proxy mechanism (also in ECMAscript Harmony), which is closer to the Python protocol for customizing attribute access than to Ruby's method_missing.
The ruby feature that you are explaining is called "method_missing" http://rubylearning.com/satishtalim/ruby_method_missing.htm.
It's a brand new feature that is present only in some browsers like Firefox (in the spider monkey Javascript engine). In SpiderMonkey it's called "__noSuchMethod__" https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/NoSuchMethod
Please read this article from Yehuda Katz http://yehudakatz.com/2008/08/18/method_missing-in-javascript/ for more details about the upcoming implementation.
Not at the moment, no. There is a proposal for ECMAScript Harmony, called proxies, which implements a similar (actually, much more powerful) feature, but ECMAScript Harmony isn't out yet and probably won't be for a couple of years.
You can use the Proxy class.
var myObj = {
someAttr: 'foo'
};
var p = new Proxy(myObj, {
get: function (target, methodOrAttributeName) {
// target is the first argument passed into new Proxy, aka. target is myObj
// First give the target a chance to handle it
if (Object.keys(target).indexOf(methodOrAttributeName) !== -1) {
return target[methodOrAttributeName];
}
// If the target did not have the method/attribute return whatever we want
// Explicitly handle certain cases
if (methodOrAttributeName === 'specialPants') {
return 'trousers';
}
// return our generic method_missing function
return function () {
// Use the special "arguments" object to access a variable number arguments
return 'For show, myObj.someAttr="' + target.someAttr + '" and "'
+ methodOrAttributeName + '" called with: ['
+ Array.prototype.slice.call(arguments).join(',') + ']';
}
}
});
console.log(p.specialPants);
// outputs: trousers
console.log(p.unknownMethod('hi', 'bye', 'ok'));
// outputs:
// For show, myObj.someAttr="foo" and "unknownMethod" called with: [hi,bye,ok]
About
You would use p in place of myObj.
You should be careful with get because it intercepts all attribute requests of p. So, p.specialPants() would result in an error because specialPants returns a string and not a function.
What's really going on with unknownMethod is equivalent to the following:
var unk = p.unkownMethod;
unk('hi', 'bye', 'ok');
This works because functions are objects in javascript.
Bonus
If you know the number of arguments you expect, you can declare them as normal in the returned function.
eg:
...
get: function (target, name) {
return function(expectedArg1, expectedArg2) {
...
I've created a library for javascript that let you use method_missing in javascript: https://github.com/ramadis/unmiss
It uses ES6 Proxies to work. Here is an example using ES6 Class inheritance. However you can also use decorators to achieve the same results.
import { MethodMissingClass } from 'unmiss'
class Example extends MethodMissingClass {
methodMissing(name, ...args) {
console.log(`Method ${name} was called with arguments: ${args.join(' ')}`);
}
}
const instance = new Example;
instance.what('is', 'this');
> Method what was called with arguments: is this
No, there is no metaprogramming capability in javascript directly analogous to ruby's method_missing hook. The interpreter simply raises an Error which the calling code can catch but cannot be detected by the object being accessed. There are some answers here about defining functions at run time, but that's not the same thing. You can do lots of metaprogramming, changing specific instances of objects, defining functions, doing functional things like memoizing and decorators. But there's no dynamic metaprogramming of missing functions as there is in ruby or python.
I came to this question because I was looking for a way to fall through to another object if the method wasn't present on the first object. It's not quite as flexible as what your asking - for instance if a method is missing from both then it will fail.
I was thinking of doing this for a little library I've got that helps configure extjs objects in a way that also makes them more testable. I had seperate calls to actually get hold of the objects for interaction and thought this might be a nice way of sticking those calls together by effectively returning an augmented type
I can think of two ways of doing this:
Prototypes
You can do this using prototypes - as stuff falls through to the prototype if it isn't on the actual object. It seems like this wouldn't work if the set of functions you want drop through to use the this keyword - obviously your object wont know or care about stuff that the other one knows about.
If its all your own code and you aren't using this and constructors ... which is a good idea for lots of reasons then you can do it like this:
var makeHorse = function () {
var neigh = "neigh";
return {
doTheNoise: function () {
return neigh + " is all im saying"
},
setNeigh: function (newNoise) {
neigh = newNoise;
}
}
};
var createSomething = function (fallThrough) {
var constructor = function () {};
constructor.prototype = fallThrough;
var instance = new constructor();
instance.someMethod = function () {
console.log("aaaaa");
};
instance.callTheOther = function () {
var theNoise = instance.doTheNoise();
console.log(theNoise);
};
return instance;
};
var firstHorse = makeHorse();
var secondHorse = makeHorse();
secondHorse.setNeigh("mooo");
var firstWrapper = createSomething(firstHorse);
var secondWrapper = createSomething(secondHorse);
var nothingWrapper = createSomething();
firstWrapper.someMethod();
firstWrapper.callTheOther();
console.log(firstWrapper.doTheNoise());
secondWrapper.someMethod();
secondWrapper.callTheOther();
console.log(secondWrapper.doTheNoise());
nothingWrapper.someMethod();
//this call fails as we dont have this method on the fall through object (which is undefined)
console.log(nothingWrapper.doTheNoise());
This doesn't work for my use case as the extjs guys have not only mistakenly used 'this' they've also built a whole crazy classical inheritance type system on the principal of using prototypes and 'this'.
This is actually the first time I've used prototypes/constructors and I was slightly baffled that you can't just set the prototype - you also have to use a constructor. There is a magic field in objects (at least in firefox) call __proto which is basically the real prototype. it seems the actual prototype field is only used at construction time... how confusing!
Copying methods
This method is probably more expensive but seems more elegant to me and will also work on code that is using this (eg so you can use it to wrap library objects). It will also work on stuff written using the functional/closure style aswell - I've just illustrated it with this/constructors to show it works with stuff like that.
Here's the mods:
//this is now a constructor
var MakeHorse = function () {
this.neigh = "neigh";
};
MakeHorse.prototype.doTheNoise = function () {
return this.neigh + " is all im saying"
};
MakeHorse.prototype.setNeigh = function (newNoise) {
this.neigh = newNoise;
};
var createSomething = function (fallThrough) {
var instance = {
someMethod : function () {
console.log("aaaaa");
},
callTheOther : function () {
//note this has had to change to directly call the fallThrough object
var theNoise = fallThrough.doTheNoise();
console.log(theNoise);
}
};
//copy stuff over but not if it already exists
for (var propertyName in fallThrough)
if (!instance.hasOwnProperty(propertyName))
instance[propertyName] = fallThrough[propertyName];
return instance;
};
var firstHorse = new MakeHorse();
var secondHorse = new MakeHorse();
secondHorse.setNeigh("mooo");
var firstWrapper = createSomething(firstHorse);
var secondWrapper = createSomething(secondHorse);
var nothingWrapper = createSomething();
firstWrapper.someMethod();
firstWrapper.callTheOther();
console.log(firstWrapper.doTheNoise());
secondWrapper.someMethod();
secondWrapper.callTheOther();
console.log(secondWrapper.doTheNoise());
nothingWrapper.someMethod();
//this call fails as we dont have this method on the fall through object (which is undefined)
console.log(nothingWrapper.doTheNoise());
I was actually anticipating having to use bind in there somewhere but it appears not to be necessary.
Not to my knowledge, but you can simulate it by initializing the function to null at first and then replacing the implementation later.
var foo = null;
var bar = function() { alert(foo()); } // Appear to use foo before definition
// ...
foo = function() { return "ABC"; } /* Define the function */
bar(); /* Alert box pops up with "ABC" */
This trick is similar to a C# trick for implementing recursive lambdas, as described here.
The only downside is that if you do use foo before it's defined, you'll get an error for trying to call null as though it were a function, rather than a more descriptive error message. But you would expect to get some error message for using a function before it's defined.
This is more of an exploratory question, seeing how the core JavaScript stuff works. I realize the convention is to not override any core JavaScript classes, but I just can't seem to wrap my head around this one.
You can create what acts like "class methods" in JavaScript by adding to the core Function prototype like this:
Function.prototype.class_method = function() {
console.log("class method called")
}
var User;
User = (function() {
function User() {}
return User;
})();
User.class_method(); // "class method called"
My question is, is there a way to add "instance methods" in a similar way? Something crazy like this, but what's below doesn't work (or make any sense):
alias = Function.prototype.constructor;
Function.prototype.constructor = function() {
child = this;
child.prototype.instance_method = function() {
console.log("instance method called");
}
alias.apply(child);
}
var user = new User();
user.instance_method(); // method doesn't exist
It's almost like you'd need to override the Function class' constructor method and access the prototype from there. Is this possible?
It does work if you add to the Object.prototype like this:
Object.prototype.instance_method = function() {
console.log("instance method");
}
var user = new User();
user.instance_method(); // "instance method called"
But that doesn't seem right either, mainly because seeing the output in the node.js console from console.log({}); change is confusing:
console.log({});
// {};
Object.prototype.instance_method = function() {
console.log("instance method");
}
console.log({});
// {"instance_method": [Function]}
If you are using node.js, you should be able to use Object.defineProperty [MDN] and make the new property non-enumerable:
Object.defineProperty(Object.prototype, 'instance_Method', {
value: function() {
console.log("instance method");
},
enumerable: false // it's already the default
});
This was introduced in ECMAScript5, so only newer browsers will support it.
It's important to understand when the prototype comes into play. It's simply an object that is a property of a function. It only has meaning when you use the new keyword. Example:
var Widget = function(val) {
this.value = val;
};
Widget.prototype.getValue = function() {
return this.value;
};
var widget1 = new Widget('test');
widget1.getValue(); // test
var widget2 = new Widget('test2');
widget2.getValue(); // test2
When new is used, the js interpreter will create a hidden _proto_ property on the instance. This proto link is simply a reference to the prototype object of the constructor function, e.g., Widget at the time the constructor was called.
When you override the Function constructor, you are literally adding something that will be on the _proto_ property of every function created after you modified Function.prototype.
If you make the statement child.prototype... = ... in your base 'class' constructor function, then that prototype will not have meaning until something 'instantiates' child, e.g., var child = new child();.
A great Resource.
To answer your question about 'instance methods', you simply need to do something like the following:
var Widget = function() {
this.method = function() {
return 'instance method';
};
};
Widget.prototype.method = function() {
return 'class method';
};
var widget1 = new Widget();
widget1.method(); // instance method
delete widget1.method;
widget1.method(); // class method
This is due to javascript's implementation of Prototypical Inheritance. The proto link I spoke of before is key here. When widget1 was first created, inside the constructor function Widget, method was attached specifically to widget1. This method will not be available to other instances. However, method on the prototype is shared across all instances of Widget.
At runtime, when the js interpreter sees widget1.method();, it first sees if widget1 has method as a property directly on it (objects in js are just hashmaps in essence, in which the keys are called 'properties'). It finds the instance method as a property in this case. However, once you delete the instance method, it will attempt to follow the _proto_ link, which is just an object reference to Widget.prototype (at the time the constructor was called). Widget.prototype.method is defined; therefore, the interpreter will execute that. If no method function is found when continuing to follow _proto_ links, it'll be a run-time error.