Javascript - get class owner of a function(method) - javascript

there is a way to know what class own a function?
Example:
function globalFunc(){
//alert MyObject
}
function MyObject(){
}
MyObject.prototype.test=function(){
globalFunc();
}
var o=new MyObject();
o.test(); //alert MyObject
Now im using this workaround:
function globalFunc(){
alert(globalFunc.caller.__class__);
}
function MyObject(){
}
MyObject.prototype.test=function(){
globalFunc();
}
MyObject.prototype.test.__class__=MyObject;
var o=new MyObject();
o.test(); //alert MyObject
But there is a big problem, look this:
function globalFunc(){
alert(globalFunc.caller.__class__);
}
function MyObject(){
}
MyObject.prototype.test=function(){
var temp=function(){
globalFunc();
}
temp();
/* to simulate a simple closure, this may be for example:
element.addEventListener("click",temp,false);
*/
}
MyObject.prototype.test.__class__=MyObject;
var o=new MyObject();
o.test(); //alert undefined
So, there is a clear way to obtain this?
I know where is the problem(class property is a property of only test and not temp), but i can't add class to temp too.
Thanks.
Thanks for reply, some clarification.
Im trying to do a personal framwork OO oriented with private members.
So:
globalFunc is a special function, im using it to get "private" property and i can't call it with call method or passing some arguments, the only arguments im pass is "this":
Example, $() is global
Class({
public:{
MyClass:function(){
},
setName:function(name) {
$(this).name=name; //set the private var name
},
getName:function(){
return $(this).name;
}
},
private:{
name:"UNKNOWN"
}
})
var o=new MyClass();
o.getName(); // UNKNOWN
o.setName("TEST!!!");
o.getName(); // TEST!!!
o.name; //undefined
$(o).name; //undefined
To works with inheritance, $(), i need to know what class call it and the object of the class.
All works good, but if i need to access a private members in a clousure i must add
__class__
property to clouser!! And i not want this!
Thanks again and sorry for my bad english, im not native speaker.

In javascript there are no Classes. Instead several objects can "own" the same function. For example:
function myFun(){
alert(this.name);
}
function Obj1(){
this.name = "obj1";
}
Obj1.prototype.fun = myFun;
function Obj2(){
this.name = "obj2";
}
Obj2.prototype.fun = myFun;
var obj1 = new Obj1();
var obj2 = new Obj2();
obj1.fun();
obj2.fun();

You scenario is not entirely clear but here are some options:-
function globalFunc()
{
alert(this.__class__);
//Note globalFunc now has access to much more.
}
function MyObject(){ }
MyObject.prototype.test=function(){
globalFunc.call(this);
}
MyObject.prototype.__class__=MyObject;
To add a closure for event handling
MyObject.prototype.test = function(){
var self = this;
var elem = //get some element;
//Not cross-browser but for illustration
elem.addEventListener('click', fnEvent);
function fnEvent() { globalFunc.call(self); }
elem = null
}

I don't understand well what you are trying to do, but here's an idea that could inspire you something.
The "constructor" property helped me well when I was trying to use JS as a OO language.
o.constructor will give you the myObject function reference.
But in my opinion, you should give functional programming a try instead of OO to get the most from Javascript

temp is the caller but it does not have the property __class__. You only defined that for test.

caller is non-standardised and really brittle; best avoided. Much better to pass the value explicitly:
MyObject.prototype.test= function() {
element.addEventListener('click', function() {
globalFunc(MyObject);
});
};
or:
MyObject.prototype.test= function() {
var myclass= arguments.callee.__class__;
element.addEventListener('click', function() {
globalFunc(myclass);
});
};

Functions are not "owned" in JavaScript. Functions are first class objects in JavaScript, which means they can be passed around like any other variable and assigned as properties of many objects.
this inside a function body will give you a reference to the object on which the function was called, if called as a method (e.g. myObj.myMethod()) or via the Function prototype's call() or apply() methods (e.g. myFunc.call(myObj)). Inside a function called on its own (e.g. myFunc()), this will usually be the global object (the same as window in most browsers).

Short answer, there really is no way to do what you are trying to do. Javascript just doesn't work like that.
Long answer...
Almost every programmer I've met who has come to JavaScript from a language that uses a classical object model has tried to do what you are doing: emulate the classical OOP style they are used to with Javascript.
There is no shame here, I did this, even the famous Douglas Crockford experimented with this, and then later gave it up. I did too. I still think it was a neccessary thing for me to try this stuff in order to really learn the langauage
Do not be fooled by the curly braces, and familiar looking operators. At it's core it has very little in common with Java! JavaScript is a functional langauge: functions are objects in their own right.
Bluntly: There is no way to do what you are trying to do - have objects with private properties you can access through this
Saying that is easy :) Understanding how to apply that is more difficult
There are no classes, there are only objects.
Objects only have properties.
Properties of objects may have values.
Those values may be functions.
this is set when the function gets called, it could be anything
Closure is the only way to achieve true privacy in JavaScript. Everything else either leaks into some enclosing scope, relies on obfuscated property names, or can be circumvented in some way by the caller, or leaks memory even after your objects are no longer referenced (as there are no destructor function to do your clean-up in).
What you are doing is still a good thing to try and do, by attempting it you will become a better JavaScript programmer by figuring out:
why you can't do some of it
more importantly why you probably shouldn't

Related

Javascript nested prototypes

The other day I was fiddling with Javascript, and I noticed that I can't write a prototype to an object within a prototype function. Like this:
var obj = function() { }
obj.prototype.First = function() {
this.prototype.Second = function() {
alert("Second Prototype");
}
}
obj.First();
obj.Second();
For some reason, the second prototype won't work and the code doesn't run. Is my syntax wrong or are there some prototype limitations that I don't know about? Thanks!
Edit:
I'm not trying to add a prototype to a prototype... that wouldn't make much sense. This is what I'm trying to do: Add two separate prototypes to obj. Prototype 2 is defined when prototype 1 is called. I thought that this would contain a reference to object, so this.prototype would be the same as obj.prototype, but it doesn't work as expected.
This is an old question, but I thought I'd add my two cents.
This code is trying to add functions on 'prototype'. However, this can only be done on the class name. What you have is a variable pointing to an anonymous class. To access the variable of an anonymous variable use 'proto'. The below is the same as your example, except, using proto it is 'successful'. Although, I don't see the benefit of using prototypes like this as the prototype added methods only apply to the anonymous instance 'obj'. http://jsbin.com/zapocamipi/edit?js,console
var obj = function() { }
obj.__proto__.First = function() {
console.log("First Prototype");
this.__proto__.Second = function() {
console.log(this);
}
}
obj.First();
obj.Second();
Maybe this could help you out understanding the role of a constructor function and the prototype.
Depending on what you're trying to do (obj, First and Second doesn't really show your intention) you could do:
A Person has Eyes. This can be done through composition.
An Employer is a Person but a Person is not necessarily an Employer (can be Client or Consultant too). This could be done through inheritance.
A Cat can move. In a Class based language Cat has to implement Movable but in JavaScript you can use mix ins and leave the implementation to the default implementation that Movable provides or override it. JavaScript does not compile time check if you do implement certain things.
If you would like to change the type of the object instance after calling a certain function then it's dangerous to meddle with the prototype because that will affect all instances of that type.
Maybe you should return an instance of another type.
var Customer = function(name) {
this.name=name || 'unknown';
};
Customer.createVipCustomer = function() {
return new VipCustomer(this);
}
var VipCustomer=function(customer){
//re use Customer constructor
Customer.call(this,customer.name);
this.isVip=true;
}
//inherit the protype defined members
VipCustomer.prototype=Object.create(Customer.prototype);
VipCustomer.prototype.constructor=VipCustomer;
VipCustomer.prototype.second=function(){
console.log('this is second');
}
var aCustomer = new Customer('Ben');
//update to VipCustomer
aCustomer = Customer.createVipCustomer(aCustomer);
aCustomer.second();
this.prototype doesn't exist.
If you want to add a property to the instance, use this.
If you want to add a property to the prototype, use Constructor.prototype.
Also, obj is a function (class), not an instance,
You want to create an instance using the new keyword, and you should name the constructor function as UpperCamelCase.

Saving instance values in a javascript class using the prototype pattern

I'll admit I'm flailing around, cobbling code together from different authors in an attempt to figure out javascript prototypes.
I'm new to the prototype concept, and would like to have some instance variables in my class that can be modified using a method.
Here's what I'm trying, in essence. This was cribbed and modified from the web:
var MyGlobe = function () {
var self = this;
self.variable1 = null;
return self;
}
MyGlobe.prototype = function () {
var setup = function () {
this.variable1 = 33;
};
return {
setup:setup
};
}();
...the point of all that is so I can call the setup method on an instance of MyGlobe and set variable1 properly:
var aGlobe = new MyGlobe();
aGlobe.setup();
//aGlobe.variable1 is 33 now
This actually seems to work, but I'm not sure why the original author did things this way? For instance, what's the point of the self.variable1 bit at the beginning?
Is it preferable to typing out:
MyGlobe.prototype.variable1;
MyGlobe.prototype.variable2;
//....
I also thought you'd do something like self=this if you thought your class would be used in a callback function for example, but that doesn't appear to be the case here? (Happy to be shown wrong.)
I'm not sure what the best practices are here and would like to know more.
This actually seems to work, but I'm not sure why the original author did things this way? For instance, what's the point of the self.variable1 bit at the beginning?
None (for using self), the "declaration of instance properties" (even if only initialising them to null) can help engines to use more memory-efficient internal structures - though it's not really necessary.
I also thought you'd do something like self=this if you thought your class would be used in a callback function for example, but that doesn't appear to be the case here?
Exactly. This small snippet really should be rewritten to
var MyGlobe = function () {
this.variable1 = null;
}
MyGlobe.prototype.setup = function() {
this.variable1 = 33;
};
Is it better to declare the instance variables in the constructor function (self.variable1) as opposed to adding them to the prototype (MyGlobe.prototype.variable1)?
That's simple. On the prototype it's no instance property any more. And please distinguish between variables (like self - which are local-scoped to the function) and properties (like prototype, setup or variable1 - which are "public" on the object).

A few questions about how JavaScript works

I have been looking deeply into JavaScript lately to fully understand the language and have a few nagging questions that I can not seem to find answers to (Specifically dealing with Object Oriented programming).
Assuming the following code:
function TestObject()
{
this.fA = function()
{
// do stuff
}
this.fB = testB;
function testB()
{
// do stuff
}
}
TestObject.prototype = {
fC : function
{
// do stuff
}
}
What is the difference between functions fA and fB? Do they behave exactly the same in scope and potential ability? Is it just convention or is one way technically better or proper?
If there is only ever going to be one instance of an object at any given time, would adding a function to the prototype such as fC even be worthwhile? Is there any benefit to doing so? Is the prototype only really useful when dealing with many instances of an object or inheritance?
And what is technically the "proper" way to add methods to the prototype the way I have above or calling TestObject.prototype.functionName = function(){} every time?
I am looking to keep my JavaScript code as clean and readable as possible but am also very interested in what the proper conventions for Objects are in the language. I come from a Java and PHP background and am trying to not make any assumptions about how JavaScript works since I know it is very different being prototype based.
What is the difference between functions fA and fB
In practice, nothing. The primary difference between a function expression (fA) and a function declaration (fB) is when the function is created (declared functions are available before any code is executed, whereas a function expression isn't available until the expression is actually executed). There are also various quirks associated with function expressions that you may stumble across.
In the example, I'd use a function expression, simply because declaring a function expression, then assigning the result seems a bit abstracted. But there is nothing "right" or "wrong" about either approach.
If there is only ever going to be one instance of an object at any given time, would adding a function to the prototype such as fC even be worthwhile?
No. Just about everyone who goes does inheritance finds that plain objects are often simpler and therefore "better". Prototype inheritance is very handy for patching built–in objects though (e.g. adding Array.prototype.each where absent).
And what is technically the "proper" way to add methods to the prototype…
There isn't one. Replacing the default prototype with some other object seems like a bit of a waste, but assigning an object created by a literal is perhaps tidier and easier to read that sequential assignments. For one or two assignments, I'd use:
Constructor.prototype.method = function(){…}
but for lots of methods I'd use an object literal. Some even use a classic extend function and do:
myLib.extend(Constructor.prototype, {
method: function(){…}
});
Which is good for adding methods if some have already been defined.
Have a look at some libraries and decide what you like, some mix and match. Do whatever suits a particular circumstance, often it's simply a matter of getting enough code to all look the same, then it will look neat whatever pattern you've chosen.
fA and fB are effectively the same and it is just a matter of convention.
If there is only one instance of a object I wouldn't even use a constructor function, but rather just a object literal, such as:
var o = {
fA: function () { ... },
fB: function () { ... },
fC: function () { ... }
};
As for adding it to an instance or a prototype, the instance is slightly more efficient than adding it to the prototype if you only have one instance but, as I said, use a literal instead.
I avoid declaring functions in the constructor because each invocation of the constructor will create new object representing each function. These objects are not very large they tend to add up if many objects are created. If the functions can be moved to the prototype, it is much more efficient to do so.
As for adding to the prototype, I favor the
TestObject.prototype.functionName = function () { };
style but it is a matter of preference. I like the above because it looks the same whether you are extending the prototype or creating the intial prototype.
Also are there any definitive JavaScript style guides or documentation
about how JavaScript operates at a low level?
Damn no javascript programmer should ever miss "Professional JavaScript for Web Developers". This is a fantastic book, that goes into the deep. It explains objects, class emulation, functions, scopes and much much more. It is also a JS reference.
And what is technically the "proper" way to add methods to the
prototype the way I have above or calling
TestObject.prototype.functionName = function(){} every time?
As for the way to define classes, I would recommend to have a look at various JS MVC frameworks (like Spine.js, which is lightweight ). You do not need the whole of them, just their class emulation libraries. The main reason for this, is that JS does not have the concept of classes, rather it is purely consisted of objects and prototypes. On the other hand classes can be perfectly emulated (please do not take the word emulated as it is something missing). As this needs some discipline from the programmer, it is better to have a class emulation library to do the job and make you code cleaner.
The standard methods that a programmer should expect of a class emulation library are:
// define a new Class
var AClass = Class.create({
// Object members (aka prototype),
// usually an initialize() method is called if it is defined
// as the "constructor" function when a class object is created
}, {
// Static members
});
// create a child class that inherits methods and attributes from parent
var ChildClass = AClass.extend({
// Child object members
},{
// Child static members
});
AClass.include({
// Object amendments (aka mixin), methods and attributes
// to be injected to the class object
},{
// Statics amendments, methods and attributes to be
// injected as class static members
});
// check object type
var aObj = new AClass();
aObj instanceof AClass; // true
aObj instanceof ChildClass; // false
var cObj = new ChildClass();
cObj instanceof AClass; // true
cObj instanceof ChildClass; // true
I answer for first part: there is no differences, when you declare function not as variable then declaration of it rises in the block, so
...
func();
...
function func () { ... }
is equal to
var func = function () { ... };
...
func();
...
So your code
function TestObject () {
this.fA = function() { // do stuff };
this.fB = testB;
function testB() { // do stuff }
}
is equal to
function TestObject () {
var testB = function () { // do stuff };
this.fA = function () { // do stuff };
this.fB = testB;
}

is there a way to inject privileged methods after an object is constructed?

I'm trying to write fully automated unit tests in JavaScript and I'm looking for a way to read some private variables in various JS functions. I thought I recalled a way to inject privileged members into a function/object (and found an overwhelming occurrence of "no such thing as private in JS") and yet I can't find any resources indicating how.
I'm trying to read through the properties of .prototype but if there's a way, someone out here would know where to direct me faster than I'd find on my own.
Thanks
Update
Privileged means a function that is usable from outside an object and has access to read "private" variables (variables otherwise unable to read from outside). See http://javascript.crockford.com/private.html for Crockford's explanations.
A sample of the function I'm trying to inject to is o2, where I need to validate the value of x (this is a simplified example, the actual code does some transformations and sends them off to other functions which I plan on testing separately).
var o2 = function() {
var x = 'me';
};
Update 2:
Thanks to everyone who's taken the time to respond. I'm seeing that the overwhelming response here is, "private is private" despite the commentary I see in other SA questions where people say "nothing in JS is private". I guess that is more like rhetorical commentary rather than what I was hoping was some kind of insight into a potential loophole I didn't yet know about.
Correct answer to your question
Even if we try to help you as much as we can, the correct answer to your question is simple:
...you can't
What good would closure variables be if we could access them directly from outside of closure?
if you had an object with private variables, they wouldn't be accessible outside function closure, which is the constructor function.
var c = function() {
var priv = "private";
this.get = function() {
return priv;
};
}
var o = new c();
o.injected = function() {
return priv; // ERROR!!!!!! priv doesn't exist in function scope
};
It is of course different matter if you enclose the whole thing inside a function closure but then you wouldn't have object privates, but rather function closure internals that would be shared among all prototypes within this closure.
(function(){
var intrn = "internal";
// omit "var" to make it global
c = function() {
this.get = function() {
return intrn;
};
};
// omit "var" to make it global
o = new c();
o.injected = function() {
return intrn; // WORKS
};
})();
o.injected();
but this is different than object privates...
Know that I am quite late to the party, but yes it is possible. Although AFAIK it requires use of eval() and a helper method:
function foo(){
var a = 'a';
this.addMethod = function(prop, val){
this[prop] = eval('(' + val.toString() + ')');
}
}
var bar = new foo();
bar.b = 'b';
var Fn = function(){return a + this.b}
bar.addMethod('getValue', Fn);
bar.getValue(); //yields 'ab'
You can use eval() in this case to redefine the function within the context of the closure. However, using eval() is dangerous, ESPECIALLY don't eval() any user input, EVER. However, for use in a testing suite/script it should be fine.
I'd suggest you read Crockford's treatise on how to achieve privileged and private in javascript objects.
If by privileged, you mean methods that are not accessible outside the object, but are callable by other methods and are actually methods on the object, then there really isn't any way to do that because one you put a method on the object, javascript let's anyone call it.
If you just wanted to add a function that was only callable by methods, you could do that by having a private member variable (see how Crockford implements that) that was an object and you could put the methods on that object. Then all existing methods (implemented the way Crockford suggests in the constructor to have access to the private member data) could call those methods. They would technically be members of a different object, but could be given private access to your object's instance data if needed.
It's all pretty convoluted so you'd probably get a better answer if you described the problem you're really trying to solve.
I don't think you can do that. Consider the following code:
function foo() {
var privateVar = 10;
this.privilegedMethod = function() {
return privateVar;
}
}
var obj = new foo();
Here, privilegedMethod has access to privateVar, since it's part of the closure created when the method was defined. Of course, you can always attach a new method to the object after instantiation:
obj.newMethod = function() { return "hello" };
alert(obj.newMethod()); // alerts "hello"
But this new method won't have access to privateVar.

Why cant I declare a constructor instantiate an object and then access the prototype?

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

Categories