What's substantive difference between function and Object in javascript? - javascript

When I learn js at first I get a voice which say everything is an object, so I think maybe function is an object and object is an object too.
But when I learn prototype, some thing different to my thought.
function helloworld(){
this.hi = 'world';
}
var foo = {
'sth':'happend'
};
function bar(){};
bar.prototype = foo;
console.log(new bar().sth);
bar.prototype = helloworld;
console.log(new bar().hi);
And I get print
happend
undefined
Then I replace bar.prototype = helloworld; to bar.prototype = new helloworld(); I get correct result.
happend
world
I'm a newbie, maybe it's a stupid question, but I really want to know what's wrong in my mind? is function not an Object? could anybody help me? thanks a lot..

Yes, a function is an object, and can have properties as well:
var foo = {};
var bar = function(x){return x+1};
foo.prop = "hello ";
bar.prop = "world!"; // works the same!
alert(foo.prop + bar.prop);
What's substantive difference between function and Object?
Well, a function is an object that can be called - "normal" objects can't:
bar(4); // 5
foo(4); // Error: 'foo' is not a function
I replace bar.prototype = helloworld; with bar.prototype = new helloworld(); to get correct result
I really want to know what's wrong in my mind?
You must not confuse constructor functions for instances that were created by calling them. helloworld is an object (just as bar is in the example above), but it's a very different object than new helloworld() (which inherits from helloworld.prototype, and was initialised by the constructor with a hi property).

Related

Learning .prototype

Edit: for those people seeing this post in the future, this site was undoubtedly critical for me to digest Javascript. If you're coming from a traditional OOP background, I HIGHLY recommend it. The UML-esq diagrams were amazing.
I still can't get my head around what the .prototype property in Javascript is. Is it simply a reference to another object? Or is it a reference to a pointer to another object? I come from C/C++/x86 and just can't see how it works. Let's look at some examples of how I currently see things; it'd help to point out my errors to see how things work. I don't even know if some of these are valid syntax. Object and Function are the global object/function objects respectively.
1 // Global.prototype = ??
2 // Function.prototype = ??
3
4 var obj1 = {}; // obj1.prototype = Object
5 obj2 = {}; // obj2.prototype = Object
6
7 var func1 = function() {}; // func1.prototype = Function
8 func2 = function() {}; // func2.prototype = Function
9 function func3() {} // func3.prototype = Function
10
I'm so confused.
11 var Foo = function() { this.prop1 = 0; }
12 var foo = new Foo(); // should it be 'new Foo' or 'new Foo()'?
13 // Foo.prototype = Function
14 // foo.prototype = Foo
15 var Goo = function() { this.prop2 = 0; }
16 var goo = new Goo();
17 // goo.prototype = Goo
18 goo.prototype = new Foo();
19 // goo.prop1 now exists ?
I also don't understand swapping prototypes around.
20 function A () {
21 this.prop1 = 1;
22 }
23 function B () {
24 this.prop2 = 2;
25 }
26 function C () {
27 this.prop3 = 3;
28 }
29 C.prototype = new B();
30 var c = new C();
31 // c.prop1 = 1
32 // c.prop2 = 2
33 // c.prop3 = undefined
34 C.prototype = new A();
35 // c.prop2 = 2???
36 // c.prop3 = 3
I can't get a grasp on the concept. I don't quite understand. I don't get how cloned objects get their own local copies of data, but changes to the original object (the prototype) somehow cascade down to the clones. I've been fiddling around with FigureBug trying things out, but mentally I can't come up with an idea that is consistent with every example ive seen
C++ may be a huge monstrosity, but at least I know exactly what's going. Here... I'm using my best guess..
Just a new paradigm I suppose. Anyways, thanks if you can help out... I'm turned upside-down on this .prototype.
Wow, that's a lot of questions. Let's work through them.
Is it simply a reference to another object? Or is it a reference to a pointer to another object?
There are no pointers in JavaScript. Yet, a variable or property holding "an object" is actually holding a reference to the object, so other variables can hold references to the same object.
Global.prototype = ??
The global object (window if you want), where all global variables are defined, has no prototype (don't care about exceptions in some environments).
I still can't get my head around what the .prototype property in Javascript is.
The .prototype property is a property that all function objects have, pointing to their prototype object (a plain object).
You must not confuse it with the internal prototype reference which each object has. That prototype points to the object where properties are looked up which an object doesn't have itself.
Function.prototype = ??
This is the object from which all Function objects inherit. It contains things like call or bind.
var obj1 = {}; // obj1.prototype = Object
var func1 = function() {}; // func1.prototype = Function
Yes, kinda. I think you've got the concept, but didn't know the terminology. While func.prototype is a different thing, the obj.prototype property doesn't even exist. However, you meant the internal prototypes - we can access them via the Object.getPrototypeOf function. And they don't refer to the constructor functions, but their prototype objects. Here's the correction:
Object.getPrototypeOf(obj1) === Object.prototype
Object.getPrototypeOf(func1) === Function.prototype
should it be 'new Foo' or 'new Foo()'?
That doesn't matter, they're equivalent. You only need the brackets explicitly when you want to pass arguments.
var Foo = function() { this.prop1 = 0; }
var foo = new Foo();
Again, your assumptions were correct but expressed wrong. Let's work through the details.
Above, I've talked about "prototype objects". What are those? They are plain objects which get implicitly created with every function. In this case, it's Foo.prototype - an empty object. So we deal here with three objects: The Foo constructor function, its Foo.prototype prototype object and the foo instance.
What's special about foo? It's the first thing which the new operator does. When a function is getting invoked as a constructor - with new - then its .prototype property is accessed and a new object is instantiated with its internal prototype set to that prototype object. That's the miraculous thing. After that the function is called on the new instance so that this is the new object; and in your case it creates the .prop1 property on the instance. Then the result is returned (and assigned to foo).
How to make use of that magic now? The point is to create properties on the prototype object, which will be inherited then.
// modify `Foo.prototype`, the object which `foo` inherits from:
Foo.prototype.prop2 = 1;
console.log(foo.prop2); // 1!
I also don't understand swapping prototypes around.
The problem is that this is quite impossible. Once instantiated, an object's prototype chain is quite static. However, you don't need that often.
goo.prototype = new Foo();
That didn't work because the .prototype property is not what you expected.
var c = new C();
C.prototype = new A();
That does work only a littlebit. Have a look above at what new does - it looks up the .prototype property of the constructor only once. The internal prototype stays locked then - you don't change the c instance. However, if you would create a new instance var d = new C() now then it would inherit from the A instance.
I hope this helps; if you have further questions please comment.
The prototype is used to search properties when the object itself doesn't have it defined, during reads. Writes always happen on the object itself
When you call
// An instance of Foo ({prop1:0}) is set as the
// prototype (to all instances of Goo)
var goo = new Goo();
// 0, from the prototype
console.log(goo.prop1);
// Read from the object itself (set in Goo's constructor)
console.log(goo.prop2);
// New instance, same prototype as goo
var goo2 = new Goo();
console.log(goo2.prop1) ; // 0, still from the prototype
// Setting is always at the object level, not the prototype
goo.prop1 = 5;
// goo2 is still reading from the prototype
console.log(goo2.prop1);
N.B.
Don't instantiate the parent class just to setup inheritance. See why here http://js-bits.blogspot.com/2010/08/javascript-inheritance-done-right.html

Performance disadvantages of using this javascript pattern?

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.

How to differentiate between factory objects and functions?

I learnt that one way objects could be created in JavaScript (factory function) is as follows:
var newPerson=function(name){
var result = new Object();
result.name = name;
result.getName = function(){
return this.name;
};
return result;
};
var personOne = newPerson("Diego");
var personTwo = newPerson("Gangelo");
console.log(personOne.getName()); // prints Diego
console.log(personTwo.getName()); // prints Gangelo
Well, I found somewhere that a function could be created as follows:
var hello = new Function('alert("Hello, World!");');
So how could I know an object from a function if they're declared in the same manner?
If it helps, the line
var hello = new Function('alert("Hello, World!");');
is essentially the same as
var hello = function() { alert("Hello, World!"); };
...except for some complications around binding. In practice, there's almost never any reason to use new Function(...).
You can tell what kind of object you're dealing with using a couple of options:
typeof provides a fairly gross indication (in this case, "object" vs. "function").
Object.prototype.toString.call(whatever) gives you more information by (for objects defined by the spec) giving you strings like [object Object] or [object Function] or [object Array].
More in my blog post Say what? which deals with figuring out what things are in JavaScript (and why you rarely actually need to).
"how could i know an object from a function if they're declared in the same manner?"
Well... since the Function constructor returns function objects, you could simply use typeof to test it .
typeof hello === "function"; // true
typeof personOne === "function"; // false
The "factory function" is just a fancy term for a function you wrote that returns a new object. It's an alternate way of creating an object from using an object constructor.
So if I want a function that creates new objects, I can use a function as a constructor, which requires that I invoke it with new:
function MyObj() {
this.foo = "bar"
}
var o = new MyObj();
Or I could use this "factory" pattern:
function MyObj() {
return {
foo: "bar"
}
}
var o2 = MyObj();
Both of them create a new object, but the first way gives you an extra prototype object that you can extend without affecting other objects.
Neither of these approaches make a function object.
JavaScript has built in constructors for creating native objects and primitives. Constructors like:
Function
Array
Object
RegExp
...and so on.
These are built in to the environment, and can be used to create new native data. But JS also gives you the ability to build your own constructors. That's what I did in the example above.
Your own constructor returns an Object, but again, it is linked to a clean prototype object that can be extended for all objects created from that constructor.

improve javascript prototypal inheritance

I'm using a classical javascript prototypal inheritance, like this:
function Foo() {}
Naknek.prototype = {
//Do something
};
var Foo = window.Foo = new Foo();
I want to know how I can improve this and why I can't use this model:
var Foo = window.Foo = new function() {
};
Foo.prototype = {
//Do something
};
Why this code doesn't work? In my head this is more logical than the classical prototypal inheritance.
Your var Foo = window.Foo = new Foo(); example is...odd. First you declare a function Foo, then you assign something to its prototype (I assume you meant to replace Nannak with Foo in your second line), and then you overwrite the reference to the function by assigning to it.
Standard Javascript prototypical inheritance looks like this:
// Create a constructor `Foo`
function Foo() {
}
// Give the prototype for `Foo` objects a function bound to the
// property `bar`
Foo.prototype.bar = function() {
}
// Only do this bit if you're doing this within a function and you want
// to make `Foo` available as a property of `window` (e.g., effectively
// a global variable. If this code is already at global scope, there's
// no need to do this.
window.Foo = Foo;
Here's how you'd use Foo:
// Create a `Foo` and use its `bar`
var f = new Foo();
f.bar();
A couple of other notes:
Never use new function() { ... } unless you really, really know what you're doing. It creates an object initialized by the function, it does not create a new function. There's almost never any need for the similar (but totally different) new Function(...), either, again except for some advanced edge cases.
The function bound to bar in my example above is anonymous (the property it's bound to has a name, but the function does not). I'm not a fan of anonymous functions, but I didn't want to clutter the example above. More here.
If you use var at global scope (it wasn't clear from your question whether you were), it creates a property on the window object. You'd only need to do var Foo = window.Foo = ... if you're within a function and want to both create a propety of window and create a local variable called Foo. (Which maybe you meant to do! :-) )
The Foo.prototype = { .. }; way of assigning prototypical properties works, but it's not generally a good idea (again, unless you're pretty up-to-speed on this stuff). When you do that, you're completely replacing the prototype object used when you call the function via new, whereas if you just add properties to it (Foo.prototype.bar = ...), you're just augmenting the prototype, not replacing it. Replacing the prototype is perfectly valid, but there are some non-obvious things that can happen if you're unwary. :-)
You are using the new operator on the function expression, that causes a newly created object to be assigned to window.Foo.
That new object is not a function, therefore it doesn't have a prototype property and it cannot be invoked.
"doesn't work" is vague, but I think the root cause is new function() { (new doesn't belong here)
You probably want:
var Foo = window.Foo = function() {
};
Foo.prototype = {
bar: 'baz'
};
alert(new Foo().bar); // baz

How does 'this' work in JavaScript?

I know there are several other posts on this topic but they still leave me confused.
I've included jQuery and everything and,
I have a simple javascript class like this example:
function CarConstructor(){
this.speed=19; // in mph
this.make="Ford";
this.fillKph=fillKph;
}
function fillKph(){
$("#kphdiv").html(this.speed*1.61);
}
car1 = new CarConstructor();
car1.fillKph();
Now I know that that code snippet doesn't work and is not properly consturcted.
The "this" keyword there is referencing my dom element with the id of "kphdiv".
The question I have is what is the best way to handle this.
Ive seen one method where you set some variable equal to this (binding it) and then use that variable to reference your object. For example:
function CarConstructor(){
this.speed=19; // in mph
this.make="Ford";
this.fillKph=fillKph;
}
function fillKph(){
var me=this;
$("#kphdiv").html(me.speed*1.61);
}
car1 = new CarConstructor();
car1.fillKph();
I could also make the me a global variable ... I don't know.
I was just curious if there is another/better way.
Oh boy, you are confusing quite a few things.
function CarConstructor(){
this.speed=19; // in mph
this.make="Ford";
this.fillKph; // <-> This particular statement has no meaning.
//When you write this.fillKph without any assignment, it will be 'undefined'.
//Just because you have a function named 'fillKph' somewhere else,
//it doesn't mean it will get attached to this property.
}
Try,
var toyota = new Car();
alert(typeof toyota.fillKph); //will alert undefined.
The fillKph function is created in global scope, i.e. as property of 'Window' object.
function fillKph(){
var me=this;
$("#kphdiv").html(me.speed*1.61);
}
To fix it, you can what rezzif suggested. Your final code will look like
function Car()
{
this.speed=19; // in mph
this.make="Ford";
this.fillKph = function (){
$("#kphdiv").html(this.speed*1.61);
};
}
car1 = new Car();
car1.fillKph();
If you notice, I did not store reference to 'this' inside a local variable. Why? There is no need in this scenario. To understand more, see my detailed answer here.
If you are going to create lot of Car objects, you can define the fillKph method on the prototype.
function Car()
{
this.speed=19; // in mph
this.make="Ford";
}
Car.prototype.fillKph = function fillKph() { $("#kphdiv").html(this.speed*1.61); };
car1 = new Car();
car1.fillKph();
EDIT:
If you do something like,
function CarConstructor(){
this.speed=19; // in mph
this.make="Ford";
this.fillKph = fillKph;
}
function fillKph(){
$("#kphdiv").html(me.speed*1.61);
}
car1 = new Car();
car1.fillKph(); //This will work as expected.
But the problem is that fillKph is defined in 'Window' scope, so I can directly call it like,
fillKph(); //Calling it this way will break it as it won't get correct 'this'.
Point is,
alert(typeof fillKph); // alerts 'function' if you do it your way,
alert(typeof fillKph); // alerts 'undefined', if you do it the way I suggested, which is preferred in my opinion.
function CarConstructor(){
var _this = this;
this.speed=19; // in mph
this.make="Ford";
this.fillKph = function (){
$("#kphdiv").html(_this.speed*1.61);
};
}
car1 = new CarConstructor();
car1.fillKph();
There's completely nothing wrong with the latter method, it's perfectly fine and probably the most elegant way of doing it, it just stores a reference to the execution context in that point and time for use in another execution context where the reference points to a different object.
The confusing thing about this in javascript is it's relationship to the new operator. As you walk up the scope chain, this always refers to the last occruance of new. If need be, that means going all the way back to the window object. So if you have something like this:
function MyObject()
{
this.baz = "some value";
this.bar = function() { return this.baz; }
}
var foo = new MyObject();
alert(foo.bar());
it works as expected, because the foo variable was created with a new object/scope for the this keyword, and so the reference to this.baz points to the right place.
But then if you do this:
var foo = new MyObject();
var bar = foo.bar;
alert(bar());
expecting to call foo's bar function, you're now calling it outside of the "scope" created for foo by the new operator. Your use of this inside the bar function now looks at the window object, which doesn't have a definition for baz.
That may seem like an edge case, but it's important when working with frameworks like jQuery that create a lot of implicit objects using new or that expect you to pass functions around like variables. You have to be very careful.

Categories