JavaScript: Accessing objects in different classes - javascript

I have:
View1.prototype.function1 = function() {
this.test = "Hello";
};
And I want to call test in here:
View2.prototype.funcion2 = function() {
alert(View1.test);
};
However I get can error that View1 does not exist.
Ideas?

It's not clear to me what you are trying to do, the following may help (or not).
It's a convention in ECMAScript that variable names starting with a capital letter are constructors, e.g.
function View() {
...
}
To add a method to the constructor that is shared by all instances created from it, assign a function to the constructor's prototype:
View.prototype.f1 = function() {
this.test = "Hello";
};
Now to create an instance:
var view1 = new View();
and call the method:
view1.f1();
This calls View.prototype.f1 and passes view1 as its this value, so a test property is added with a value of "Hello":
alert(view1.test); // Hello
You can't call test since it's value is a string, and a string isn't callable. Only objects that implement the internal [[Call]] method, such as functions or host methods, are callable.
You may be struggling with prototype inheritance. If so, ask here. There are many articles on the web that attempt to explain it, but most are pretty awful.
PS: Firefox doesn't seem to like "function1" as an identifier.

View1.prototype.function1.call(View1);
View2.prototype.function2 = function() {
alert(View1.test);
};
Or change View1 to an object.

Related

How do I inherit a function from a base object and overwrite it in javascript

What I am trying to do is have a child object provide its own implementation for a function defined in a base object. As far as I've understood so far prototypes are the best (only!) way to go about doing this.
Note also that I am currently developing using the game engine: Turbulenz and as such I am trying to follow / stick to their style as closely as possible. In the engine "classes"/objects are defined and created in the following manner
function baseObject() { }
baseObject.prototype =
{
myMember1: 1,
myMember2: 2,
myMethod: function myMethodFn() {
return this.myMember1 + this.myMember2;
}
}
baseObject.Create = function baseObjectCreateFn
{
var o = new baseObject();
return o;
}
This would allow me to do the following
var anObject = baseObject.Create();
var someValue = anObject.myMethod(); // should return 3
What I would like to be able to do now is to create a new object that inherits all the properties of baseObject while allowing me to overwrite its myMethod function to for example subtract the two member values instead of add.
Would I be correct in saying that I will have to create another object then alter its prototype? The part thats throwing me most is that the definition of the baseObject's prototype is defined as an object literal and so I'm unsure of the syntax to overwrite one of its members, i.e. would the following be valid or not? :
function childObject() {}
childObject.prototype = baseObject.Create() // would this inherit from baseObject?
// or should it be: childObject.prototype = new baseObject();
// this is the part thats confusing me as the syntax
// doesn't quite match the original base objects prototype
// syntax and I'm unsure if that will matter
childObject.prototype.myMethod = function myMethodFn() {
return this.myMember1 - this.myMember2;
}
childObject.Create = function childObjectCreateFn
{
var o = new childObject();
return o;
}
var aChildObject = childObject.Create()
var anotherValue = aChildObject.myMethod() // would this return -1 as expected?
To summarise I'm trying to create an object that will overwrite a function that exists in a base object by inheriting the function from the base object and changing it, how do I do this? Thanks for your time.
You have it correct.
As for the syntax confusion, there is no real difference between
thing.prototype.myMethod = function () { ... }
and
thing.prototype = { myMethod: function() { ... } };
except for the fact that in the second one you are setting the prototype all at once (to an object literal), and if you do it again, you'll overwrite the prototype all at once with a new object literal. But because it is an object literal, you can't do inheritance this way (everything declared with naked braces { ... } is just an instance of Object of no special type). If you stick with the first syntax you'll always be ok.
Note that when you put:
childObject.prototype.myMethod = function myMethodFn() { ... }
The part where you put myMethodFn is actually ignored. The function is named myMethod by the fact that this is where you assigned it.
Similarly, where you have
childObject.Create = function childObjectCreateFn
you don't need childObjectCreateFn (it's ignored), and you need to put parentheses () somewhere after function or it's a syntax error.
Moving on to the reason why this works, every created object in Javascript has a prototype. When you call a method on that object, it first looks inside the object itself to see if a key corresponding to the name of the method exists. If not, it looks in the prototype object for the same thing, and if it's not there, it goes to that object's prototype, and so on, until it gets to the root Object, which has no prototype.
In this way you can override an implementation merely by naming it the same thing, but having it appear earlier in the prototype chain. That's exactly what you're doing on childObject. It retains the functionality of baseObject because you created an instance of baseObject to serve as childObject's prototype. Then you augmented childObject's prototype with a new method of the same name, but one that comes earlier in the prototype chain.

Javascript: Accessing public method of prototype does not work

I want to create a simple class in Javascript with only one public function as follows:
function A(myTitle) {
var title = "";
this.getTitle = function() {
return title;
};
title = myTitle;
};
var anInstance = new A("first");
console.log("anInstance.getTitle(): '"+anInstance.getTitle()+"'");
// expecting to return "first"
This does work as expected.
Now I want to add this class as a prototype to a new class, that includes a new title variable, so that the getTitle() method returns the value of the variable instead:
var myA = new Object();
myA.title ="second";
myA.prototype = anInstance;
console.log("myA.getTitle(): '"+myA.getTitle()+"'");
// expecting to return "second"
But instead of the expected "second", it results in the following error:
TypeError: 'undefined' is not a function (evaluating 'myA.getTitle()')
What is the problem with this function access?
Update:
The key point for my question is the following: In my application I will create several thousand instances of type "A" and several more of other comparable types. Thus memory efficiency and performance do matter. So I thought it would be great to create the according methods (several more will follow, getTitle is only one example) only once and the "data objects" reference these methods. Is this possible?
If all you want is instance variables (and that's all I see you using), what's wrong with idiomatic JavaScript:
function A(title) {
this.title = title;
};
A.prototype.getTitle = function() {
return this.title;
};
var anInstance = new A("first");
var myA = new A("second");
You can implement both Self-like prototypal OO and Smalltalk-like class-based OO on top of JavaScript, but this only makes sense in case of inheritance hierarchies, where the flat model of JS (which favors composition over inheritance - it's easy to add new methods to the prototype or apply() arbitrary constructor functions, but you'll have to jump through some hoops to make inheritance work properly) is not sufficient.
As to why your code can't work: your getTitle() method returns a lexical instead of an instance variable, which takes no part in property resolution via the prototype chain and thus can't be overwritten your way; also, .prototype is a property of constructor functions which is used to initialize the internal [[Prototype]] property of newly created instances - setting .prototype on general objects has no effect whatsoever on property resolution.
Firstly JavaScript is not a class based language.
This works just as well and am unsure what you are trying to achieve with your solution:
http://jsfiddle.net/jRtD2/

javascript function object's inherit method behaviour

I've come across a behaviour of the function object. that seems to be similar to prototyping but uses a different method.
var Car = function() {
this.foo = 'shiny';
}
var Rover = function() {
this.inherit = Car;
this.inherit();
}
var Mini = function() {
this.inherit = Car;
this.inherit();
}
when a new instance of a sub class is made this.inherit method has the effect of calling the parent class on itself, so that the parent's properties and methods are available to the sub class.
var myRover = new Rover();
var myMini = new Mini();
myMini.foo = 'rusty';
console.log(myRover.foo, myMini.foo); // displays "shiny" & "rusty" respectively
I've looked in Mozilla and MSDN, but I can't seem to find it documented any where. Can anyone put a name to this behaviour and any further documentation.
I think the word inheritFrom does not make any sense here. It could be as well bar. What makes this work is the pattern that you define a member of the "subClass" function which you call on the next line.
It may be worth checking out "Classical Inheritance in JavaScript" article by Douglas Crockford for some additional ideas.
inheritFrom isn't a method that exists in JavaScript core objects. JavaScript inheritance can be accomplished in many ways as outlined in this post. What you're doing here is not really proper inheritance as you're just setting a single method in a separate object equal to a function.
First you declare a function called superClass. This function sets the foo and bar properties of the this object. When you set a method on subClass equal to superClass the this object then references the subClass function because it is the method's caller so then subClass has the properties of foo and bar set to 'foo' and 'bar'.
However, when you overwrite the foo method here:
this.foo = function() {
return this.foo;
};
You turn foo into a function.
Notice that when you add this script:
var test = new subClass();
alert(test.foo);
test.foo will be a function as you overrode its value in the subClass constructor. Adding this:
alert(test.bar);
Will alert the string 'bar' since you didn't overwrite it. Also if you call test.foo() it will simply return a pointer to the test.foo method.

Difference between a constructor and an Object

I definitely need some light on this.
What's the diference between:
var MY_APP = function(){
this.firstMethod = function(){
//something
};
this.secondMethod = function(){
//something
};
};
and
var MY_APP = {
firstKey: function(){
//something
},
secondKey: function(){
//something
}
};
besides the obvious fact that one is a Function and the other an Object, what are the differences in code flow, prototypes, patterns... whatever, and when should we use the first or the second?
I'm so spaced out in this area that i'm not sure if i'm correctly explaining the doubt, but further info can be given if you ask.
The key difference between the two is in how they are intended to be used. A constructor, as its name suggests, is designed to create and set up multiple instances of an object. An object literal on the other hand is one-off, like string and number literals, and used more often as configuration objects or global singletons (e.g. for namespacing).
There are a few subtleties about the first example to note:
When the code is executed, an anonymous function is created and assigned to MY_APP, but nothing else happens. firstMethod and secondMethod don't exist until MY_APP is explicitly called.
Depending on how MY_APP is called, the methods firstMethod and secondMethod will end up in different places:
MY_APP(): Since no context is supplied, the this defaults to window and the methods will become global.
var app1 = new MY_APP(): Due to the new keyword, a new object is created and becomes the default context. this refers to the new object, and the methods will get assigned to the new object, which subsequently gets assigned to app1. However, MY_APP.firstMethod remains undefined.
MY_APP.call(YOUR_APP): This calls my MY_APP but sets the context to be another object, YOUR_APP. The methods will get assigned to YOUR_APP, overriding any properties of YOUR_APP with the same names. This is a really flexible method that allows multiple inheritance or mixins in Javascript.
Constructors also allow another level of flexibility since functions provide closures, while object literals do not. If for example firstMethod and secondMethod rely on a common variable password that is private to the object (cannot be accessed outside the constructor), this can be achieved very simply by doing:
var MY_APP = function(){
var password = "GFHSFG";
this.firstMethod = function(){
// Do something with password
alert(password); // Woops!
};
this.secondMethod = function(){
// Do something else with password
};
};
MY_APP();
alert(password); // undefined
alert(MY_APP.password); // undefined
The first is a function, the second is an object literal. Since Functions in JS are first class objects, a function can have properties on it, just like any other object can.
Typically, if you want to create a "class" that you might be familiar with from classical inheritance languages, you would do something like
function MyClass() {...}
as is documented here http://www.crockford.com/javascript/inheritance.html
To answer the question posed in your edits, you would use them both in different situations. Object literals are used to pass configurations around. A typical usage pattern would be a method that accepts an object literal like so
something.init({
length: 10,
height: 10,
text: 'some text'
});
and so on.
You could use something similar to your first example when creating a namespace. Javascript has some interesting language features in that you can have so-called "self-invoking functions" that are of the form:
var myApp = (function(){
var firstMethod = function() {...}
...
})();
the motivations behind doing something like this are detailed here
http://sparecycles.wordpress.com/2008/06/29/advanced-javascript/
You can also investigate the differences via your favorite javascript debugging console. In firebug and chrome, I did the following:
var ol = {}; ol.prototype;
var fn = function(){}; fn.prototype;
the first line prints undefined, the second returns a prototype with a constructor of 'function'
The constructor can be reused as is, the object literal would need to be repeated or wrapped in a function to be reused.
Example of wrapping the object literal in a function:
function MY_APP() {
return {
firstKey: function(){
//something
},
secondKey: function(){
//something
}
};
}
The object created using the constructor will have it's constructor property set to the constructor function. However, as you used an anonymous function assigned to a variable instead of a named function, the constructor will still be nameless.
Other than that, there isn't really any differences. Both create anonymous functions that are assigned to the properties of the object, so the resulting objects are the same. You can compare this to assigning named functions to the properties, or using prototype functions, both having the difference that each function only exists once instead of being created over and over for each object.
There is some confusion in JavaScript regarding the difference between a function and an object.
In the first case,
var MY_APP = function() { this.v = 7; ... }
or
function MY_APP(x) { this.v = x; ... }
a function is declared, not an object. In MY_APP, this refers to the global object.
Meaning that calling the function MY_APP(7) will assign v globally to the value of 7. (and in your case the function firstMethod would be declared globally).
MY_APP(3); // The global variable v is set to 3
MY_APP(4); // The global variable v is overwritten and set to 4
To use MY_APP as an object, it needs to be instantiated, for instance
var obj1 = new MY_APP(3);
var obj2 = new MY_APP(4);
will have obj1.v to be 3, and obj2.v to be 4.
Note you can also add methods using the prototype keyword (instead of this.firstMethod...)
MY_APP.prototype.firstMethod = function () { ... }
In the second case
var MY_APP = { ... };
an object, one object, is created and its name is MY_APP. The this keywords refers to that object, MY_APP.

Baffling JavaScript Inheritance Behavior

<disclaimer>
What follows is the fruits of a thought experiment. What I'm doing
isn't the issue; the symptoms are. Thank you.
</disclaimer>
I've finally wrapped my head around constructors, prototypes, and prototypal inheritance in JavaScript. But the SomethingSpectactular method in the sample below bugs me:
function FinalClass() {
return {
FinalFunction : function() { return "FinalFunction"; },
TypeName : "FinalClass",
SomethingSpectacular : function() {
return FinalClass.prototype.SubFunction.call(this);
}
}
}
FinalClass.prototype = new SubClass();
FinalClass.constructor = FinalClass;
var f = new FinalClass();
The reasons this bugs me are:
JavaScript apparently doesn't scan the prototype chain the same way for methods as it does for properties. That is, f.SubFunction() generates an error.
To get to a method on a prototype, you have to go through at least 3 dot operations every time you want to do it. FinalClass DOT prototype DOT Subfunctino DOT call. You get the point.
Base class (prototype) methods aren't showing up in Intellisense the way I'd expect them to. This is highly annoying.
So the thought experiement was to determine what would happen if I wrote a version of inherits that inserted stub functions onto the subclass that delegated back to the prototype for you. For example, it would automatically create the following function and add it to FinalClass:
function SubFunction() { SubClass.prototype.SubFunction.call(this); }
Now, I've got just about everything mapped out and working. The inherits method, which is an extension to both Object.prototype and Function.prototype, takes a Function as its sole argument. This is the base class. The subclass is determined by analyzing Object.prototype.inherits.caller.
From there, I set the prototype and constructor on the subclass, and then start analyzing the methods on the subclass's new prototype. I build an array containing the methods on both the prototype and the base class's public interface. The end result is a nice array that contains the methods that are exposed through either the prototype or by the base class constructor's return statement.
Once I have that, I start looking for each method on the subclass. If it's not there, I add it to the subclass with the same name and signature. The body of the method, however, simply forwards the call to the base class.
Now, I can step through all this code and it works marvelously, up until I instantiate instances of the subclasses. That's when things get wonky. Here's what I've observed using Visual Studio 2008 (SP1) and Internet Explorer 8:
Prior to instantiation, BaseClass exposes no public methods. This is to be expected. The methods exposed via a class constructor's return statement won't appear until it's instantiated. I'm good with that.
Prior to instantiation, SubClass exposes the methods from BaseClass. This is exactly what I expected.
Once I declare an instance of BaseClass, it has all the members I would expect. It has its typeName and BaseFunction methods.
Once I declare an instance of SubClass, it has only those methods returned by its constructor's return statement. No members from the base class are present. All the work that was done in the inherits method to map base class methods to the subclass appears to have been lost.
The big mystery for me here is the disappearance of the methods that I added to SubClass during the execution of inherits. During its execution, I can clearly see that SubClass is being modified, and that BaseClass's functions are being propagated. But the moment I create an instace of SubClass, that information is no longer present.
I am assuming this has something to do with the constructor, or order of events, or something else that I am simply not seeing.
A Final Note: This project arose as an effort to understand the complexities of JavaScript and how its prototypal inheritance system works. I know there are existing libraries out there. I know I'm reinventing the wheel. I'm reinventing it on purpose. Sometimes, the best way to understand a thing is to build it yourself. This has already been a tremendous learning experience, but I'm just stumped at this one particular point.
THE CODE
sti.objects.inherits = function inherits(baseClass) {
var subClass = sti.objects.inherits.caller;
var baseClassName = sti.objects.getTypeName(baseClass);
var methods = sti.objects.getMethods(baseClass);
if(!sti.objects.isDefined(baseClass.typeName))
baseClass.typeName = baseClassName;
var subClass = sti.objects.inherits.caller;
var subClassName = sti.objects.getTypeName(subClass);
var temp = function() {};
temp.prototype = new baseClass();
subClass.prototype = temp.prototype;
subClass.constructor = subClass;
subClass.typeName = subClassName;
subClass.baseClass = baseClass.prototype; // Shortcut to the prototype's methods
subClass.base = baseClass; // Cache the constructor
for(var index = 0; index < methods.items.length; index++) {
var resource = methods.items[index].getFunction();
var methodName = methods.items[index].getName();
if(methodName != "" && ! sti.objects.isDefined(subClass[methodName])) {
var method = sti.objects.createOverride(baseClassName, resource);
subClass[methodName] = method;
if(typeof subClass.prototype[methodName] == "undefined") {
subClass.prototype[methodName] = method;
}
}
}
}
Object.prototype.inherits = sti.objects.inherits;
Function.prototype.inherits = sti.objects.inherits;
function BaseClass() {
return {
A : function A() {return "A";}
};
}
function SubClass() {
inherits(BaseClass);
return {
B : function B() { return "B"; }
}
}
var b = new BaseClass();
var s = new SubClass();
Your constructors are not working as constructors. When you use the new keyword Javascript creates the new object and expects your constructor to populate it with members etc. Your constructors are returning another new object, not related to the object which is associated with the constructor usage, thus the prototype is not working.
Change your constructor to something like
function FinalClass() {
this.FinalFunction = function() { return "FinalFunction"; };
this.TypeName = "FinalClass";
this.SomethingSpectacular = function() {
return FinalClass.prototype.SubFunction.call(this);
};
}
and you should see the expected inheritance behaviour. This is because the FinalClass method in this case alters the contextual object created via the 'new' mechanism. Your original method is creating another object which is not of type FinalClass.

Categories

Resources