I have been playing around with the concept of "factory functions" so consider:
var HelloWorld = function() {
return {
hello: function() { console.log('hi'); }
}
}
Which as we know is instantiated as: var helloWorld = HelloWorld(); Would the "constructor" of such a function be the function it's self? And is there any way I could just do: HelloWorld.hello() instead of "instantiating it" like a class? Or is that a whole other concept?
Take a look at following code:
var HelloWorldFactory = function(text) {
return {
hello: function() { console.log(text); }
}
};
var HelloWorld = {
hello: function() { console.log('hi2'); }
};
var helloWorld = HelloWorldFactory('hi');
helloWorld.hello();
HelloWorld.hello();
as #Quentin mentioned in comment by calling HelloWorldFactory('hi'); you are not calling js constructor but just a function which returns an object.
Doing HelloWorld.hello(); is a different concept because you just use aleardy defined object(it can be created via factory or just defined in code)
In your example you are returning an object literal with a function property. You could have returned directly a function as well. But at the end this is the factory pattern and created functions' constructor is the Function function not the HelloWorld function's prototype as it would be the case with constructors.
Functions are pure objects in JS. You can treat them just like objects. So do whatever you like to do with them.
function HelloWorld(){};
HelloWorld.thank = function(){console.log("thanks")};
HelloWorld.message = "hello";
HelloWorld.sayMessage = function(){console.log(HelloWorld.message)};
However constructor functions are slightly different. They are invoked with the new keyword and as i have mentioned above they assign their own prototype to the created object. It's one of the most complicated parts of JS. I have seen many people thinking new is useless, better be avoided and Object.create() should be preferred instead but it's not the case. There are times constructor functions are very useful since you can establish amazing prototypical relationships during the construction time.
Related
I've got a legit JS question which is kinda hard to explain. Please forgive my unintelligible manner of speaking and try to grasp the idea. :P
In JS objects can have properties. You can assign functions to properties. You can redefine properties of an object without altering its other properties.
var myObject = {};
myObject.myFunction = function() { return 1; };
myObject.bar = "Bar";
myObject.myFunction = function() { return "Another function here"; }
console.log( myObject.bar ); // This is still "bar"
But objects can themselves be functions.
Question 1: What is the correct term for the function of such a function-object? I'll call it "function-object's main function" below.
I understand that in JS all funcitons are function-objects, so it's incorrect to say "function of a function-object". But when an object 'foo' can execute two functions: foo() and foo.bar(), there should be an unambiguous way to distinguish the two in speech.
As function-objects are objects, they can have properties.
Question 2: How do i redefine the function-object's main function while leaving other function-object's properties intact?
Example of what i want:
myFunctionObject = function () { return 1; }
myFunctionObject.bar = "Bar";
// How do i do this...
myFunctionObject = function () { return "Another function here"; }
// ...so that this still returns "Bar"?
console.log( myFunctionObject.bar );
The main function of the function-object should be stored somewhere... Some hidden property maybe, e. g. myFunctionObject.__function__ = function () { return 1; }?
PS My goal is to understand JS internals. I don't mean any practical use case for this, other than solving some crazy JS-kungfu exercises on [CodeWars](http://codewars.com .
What is the correct term for the function of such a function-object? I'll call it "function-object's main function" below.
It's called a "function". The properties of the (function) object that are functions themselves are called "methods". If you're talking about methods on a constructor function, you also call them "static methods" (of the "class").
How do i redefine the function-object's main function while leaving other function-object's properties intact?
You cannot. The call behaviour of a function is immutable in javascript.
All you can do is create a new function, overwrite the variable in which the old one was stored with it, and copy over all properties.
Question 1: Adding user defined properties to functions is not recommended, because you don't control what properties functions have, so you can't know for sure if you are going to shadow another property. Since it is not recommended, I don't think there is a correct term for that. Personally, I would call them functions with user defined properties.
Question 2: The code myFunctionObject = function () { return "Another function here"; } sets myFunctionObject to a different object (function () { return "Another function here"; }). So, you need to pass the properties of your old object to the new one. One way of doing that is by using functions that add properties instead of adding properties with assignment.
function addBar(o){
o.bar = "Bar";
return o;
}
myFunctionObject = addBar(function () { return 1; });
myFunctionObject = addBar(function () { return "Another function here"; });
console.log(myFunctionObject.bar);
I am trying to duplicate private prototype methods in javascript and found this bit of code, but I do not fully understand how it implements itself.
The code is...
var Foo = function () {};
Foo.prototype = (function () {
// Private attributes
var somePrivateAttribute = 'Hello world';
// Private methods
function somePrivateMethod(val) {
alert(val);
}
// Public attributes and methods
return {
somePublicMethod: function () {
somePrivateMethod(somePrivateAttribute);
}
};
})();
What I do not understand is when this object is initiated new Foo() does that create a new object for the prototype every time as it is in a self executing function? Could anyone please explain the benefits and disadvantages of using this for a project of mine.
How would this type of pattern work for objects that could have 500 instances or just 1. I am trying to understand and would greatly appreciate if anyone could enlighten me?
Is there any performance benefits to using this method?
What I do not understand is when this object is initiated new Foo() does that create a new object for the prototype every time as it is in a self executing function?
No. That's the point of prototypes, they are not duplicated - every of your Foo instances will inherit from the same Foo.prototype object.
Could anyone please explain the benefits and disadvantages of using this for a project of mine.
It looks like you're having a little misunderstanding, regarding the naming: Those "private" things are no "attributes" or "methods", as they have absolutely nothing to do with instance objects. They are just local variables which are only accessible from the functions you assign to the prototype object.
You might want to read How do JavaScript closures work? and their use in IIFEs.
How would this type of pattern work for objects that could have 500 instances or just 1.
It's perfectly fine. However, using the constructor pattern for just 1 instance might be a little odd - singletons can be defined in a simpler way.
If you want to read more on that pattern, search for revealing prototype pattern - it's the revealing module pattern applied to create prototype objects.
I haven't seen that pattern before, using a module (that's what it's called) for the prototype... but here's what I'd recommend; it's similar but the module encloses everything:
var Foo = (function FooClass() {
var privateVar = 'Hello world';
function privateFunc() {
...
}
function Foo() {}
Foo.prototype = {
publicMethod: function() {
...
}
};
return Foo;
}());
var foo = new Foo();
What I do not understand is when this object is initiated new Foo()
does that create a new object for the prototype every time as it is in
a self executing function?
The self executing function runs once, returns the object, and it won't run again; it keeps a reference to the variables via closure.
What I do not understand is when this object is initiated new Foo() does that create a new object for the prototype every time as it is in a self executing function?
No, the assignment to Foo's prototype only happens once. Nothing wrong with it at all, just a little unconventional.
You could also write it like this (also unconventional, but accomplishes the same thing):
var Foo = function () {};
Foo.prototype = new function() {
// Private attributes
var somePrivateAttribute = 'Hello world';
// Private methods
function somePrivateMethod(val) {
alert(val);
}
// Public attributes and methods
this.constructor = Foo;
this.somePublicMethod = function () {
somePrivateMethod(somePrivateAttribute);
}
};
As Bergi pointed out, this adds an extra object to the prototype chain; if you want to avoid that, you can write it like this instead:
var Foo = function () {};
(function() {
// Private attributes
var somePrivateAttribute = 'Hello world';
// Private methods
function somePrivateMethod(val) {
alert(val);
}
// Public attributes and methods
this.somePublicMethod = function () {
somePrivateMethod(somePrivateAttribute);
}
}).call(Foo.prototype)
By modifying the prototype instead of replacing it, the constructor property also stays intact.
If I have a function say:
var my_function = function()
{
}
If the function is not called, it is not taking up memory, it is just text sitting in memory.
However if you call it by say...
function_instance = new my_function();
It is instantiated is a sort of way, and the variables and methods it contains are loaded into memory.
Is this a way to represent a class/object model similar to C++?
Is my interpretation correct?
In javascript, the class concept does not exist. Everything is an object. When you use the new operator it copies the prototype of that function into a new object. In other words, you can emulate what class can do in c++, but it's not a class.
"a way to represent a class/object model similar to C++" would be through the use of prototypes.
As Kevin M pointed out, you can use the this keyword to create instance variables in a function, like so:
var my_function(foo)
{
this.foo = foo;
this.bar = function()
{
// bar-ing here
}
}
The problem however, that whenever you instantiate my_function(), a new instance of the my_function.bar function is also created. Enter prototypes:
var barPrototype = { "bar" : function()
{
// bar-ing here
}
};
var my_function(foo)
{
this.foo = foo;
}
my_function.prototype = barPrototype;
So, to sum it all up, the prototype keyword can be used to create function-specific, inheritable properties that are analoguous to C++'s member functions. Member functions of C++ aren't instantiated for each instance of a class. Instead, the compiler adds a this pointer to the function's parameters; this pointer points to the instance that the member function is called on.
More JSey fun to be had here: http://javascript.infogami.com/Javascript_in_Ten_Minutes
In JavaScript a new class is defined by creating a function. The function may contain other functions (methods), properties, etc.
When a function is called using the new operation the function becomes a constructor for that class. Inside the constructor the variable " this " is created and points to the object.
function Man(){
this.name = 'John';
}
var person = new Man;
console.log(person.name);
As mentioned, Javascript functions can act as objects so Javascript can be object oriented but object inheritance is prototypical and not like C++. John Resig, the creator of jQuery, has done some work on emulating traditional classes and inheritance in javascript. You could take a look at his blog for an interesting example:
http://ejohn.org/blog/simple-javascript-inheritance/
The below doesnt work and im struggling to work out why....
function CommentHandler() {
var Text;
}
var myCommentHandler = new CommentHandler();
myCommentHandler.prototype.SayHello = function () {
document.write('Hello World');
}
I get the error : 'myCommentHandler.prototype is undefined'
I just cant see why? I have declared a variable called myCommentHandler and copied in the object CommentHandler then Im trying to access the protoype of it and assign a function but I cant...Anyone know why?
The prototype belongs to the class, not the instance:
CommentHandler.prototype.MyFunction = ...
However you can also access the prototype via the instance's constructor property:
myObj.constructor.prototype.MyFunction = ...
This will of course add that function to every instance of your CommentHandler.
If instead you only wanted to add that function to that one instance, you'd do:
myObj.MyFunction = ...
Note that in none of these variants would it be possible for MyFunction to access your private variable Text.
This is the compromise forced by the prototype inheritance model - variables and methods must be public (e.g. this.Text) if they're to be accessed from outside, and in this case functions declared in the prototype are effectively "outside".
The alternative (using closure-scoped variables and methods) seems more natural to OO programmers, but makes inheritance much harder.
I think what you actually want here is this:
CommentHandler.prototype.SayHello = function () {
document.write('Hello World');
};
You have to use
CommentHandler.prototype.SayHello = function(){....}
You can find more about the prototype object in the following references
http://www.javascriptkit.com/javatutors/proto.shtmlhttps://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/prototypehttp://msdn.microsoft.com/en-us/magazine/cc163419.aspx
You need to prototype the class function rather than the instance. Also if you want the Text variable to be accessible outside the constructor, in the other method functions, then you need to add the this keyword.
function CommentHandler() {
this.Text = 'Hello World';
}
CommentHandler.prototype.SayHello = function () {
document.write(this.Text);
}
var myCommentHandler = new CommentHandler();
myCommentHandler.SayHello();
As a side point you could create the SayHello function inside the constructor, but this would add increased overhead to the creation of each instance of CommentHandler. Thus the prototyping method that you are using is a better option.
myCommentHandler does not have a prototype, because it is an instance. CommentHandler does have a prototype that can be modified. I am guessing you want to edit the object after initializing, and can do so like this:
myCommentHandler.SayHello = function() {
document.write('Hello World');
}
Here is a good explanation of prototypes and object oriented programming in javascript with many examples: http://mckoss.com/jscript/object.htm
I'm hesitant to use just any tutorial because I know how those tutorials can end up being, teaching you bad ways to do things. I want to setup a class in Javascript, so that I can just do
var vehicle = new Vehicle(el);
var model = vehicle->getModel();
These functions would read the HTML and get and manage the elements on the page. I'm current doing a setup like...
var model = function () {
return {
getName: function () {
},
getVehicleCount: function () {
},
incrementCount: function (id) {
console.log(x);
}
}
}();
I'm still learning classes in Javascript... I'd like to be able to pass the class a node for the element all of the methods will use, but I'm not sure I'm doing this right...
There is no such thing as a class in JavaScript, instead everything in JavaScript is an object.
To create a new object you define a function that uses the this keyword in it (a “constructor function”), and then call it with the new operator:
function Foo (id) { // By convention, constructor functions start with a capital letter
this.id = id;
}
var foo1 = new Foo(1);
var foo2 = new Foo(2);
However, these objects have no methods. To add methods, you need to define a prototype object on their constructor function:
Foo.prototype = {
getId: function () {
return this.id;
}
}
This new getId function will be usable by all Foo objects. However, as was stated, there are no classes in JavaScript and as such there are other constructs you will use in order to produce different results.
I highly recommend the videos by Douglas Crockford in which he explains much of the javascript OO nature. The talks can be found here:
http://developer.yahoo.com/yui/theater/
Douglas Crockford — The JavaScript Programming Language
Douglas Crockford — Advanced JavaScript
Those will give you a basic understanding of the structure of javascript and should help the transition from classical to functional programming.
Although there are no classes in JavaScript, you can create constructor functions. A constructor function works by binding methods to an objects prototype. There are several ways to do this, each with advantages and disadvantages. I personally prefer the most straigthforward way, which works by appending methods to "this":
var Constructor = function() {
//object properties can be declared directly
this.property = "value";
//to add a method simply use dot notation to assign an anonymous function to an object
//property
this.method = function () {
//some code
}
//you can even add private functions here. This function will only be visible to this object methods
function private() {
//some code
}
//use return this at the end to allow chaining like in var object = new Constructor().method();
return this;
}
There is nothing like classes in JavaScript. JavaScripts inheritance works with prototypes. You can take a look at base2, which mimics class-like behaviour in JavaScript.