Getting “private method” in a “public function” class using CoffeeScript - javascript

I'm doing a series of tests with classes and CoffeeScript/JavaScript. See the following code:
class Example
someFunction = ->
alert #getText()
constructor: ->
#text = 'Hello world! ;)'
someFunction()
getText: ->
#text
### Instance ###
example = new Example
It's just an example, when compiling I get the error:
Uncaught TypeError: Object [object global] has no method 'getText'
You know how I can solve this problem?
http://jsfiddle.net/P4Xdz/

If you really want to do this sort of thing, you'll have to manually provide the correct # (AKA this) by hand with call or apply:
constructor: ->
#text = 'Hello world! ;)'
someFunction.call(#)
Demo: http://jsfiddle.net/ambiguous/6KZrs/
The problem is that someFunction is not a method of any kind, it is just a simple function. If you need it to behave like a method then you have to "methodize" it manually by providing the desired # when you call it. This (and epidemian) suggests an alternative approach: explicitly pass the object as an argument:
someFunction = (ex) ->
console.log ex.getText()
constructor: ->
#text = 'Hello world! ;)'
someFunction(#)
Demo: http://jsfiddle.net/ambiguous/hccDr/
Keep in mind that there is no public or private in JavaScript and so there is no public or private in CoffeeScript. You can sort of fake it but fakery has holes and tends to require more chicanery (such as manually supplying the # with call) to make it work. If you look at the JavaScript version of your code, you'll see that someFunction is just this:
var someFunction = function() { ... };
Just a function in a variable that is scoped to the class function, nothing more. Also keep in mind that since someFunction is local to the Example class function, it won't be visible in any way to subclasses.

This may be obvious but... coffescript isn't able to do anything conceptually you couldn't already do in javascript. Right now your someFunction definition is a local variable, and is not declared as a property on the instance (unlike getText).
When you use '#' within someFunction I'm assuming you expect it to refer to the instance of Example, which would be convenient in your case, however someFunction isn't defined on example.
If you used the => notation it still wouldn't bind it to the instance (it would refer to the class function). Now this may seem inconvenient, or an odd design choice, but its actually consistent. Once again, someFunction isn't on the instance, its defined as a local variable within the Example class function.
If you use ->, '#' refers to javascripts 'this' for that function (which is the local variable and obviously doesn't contain getText). If you use => it refers to javascripts 'this' at the time of the definition, which is at this point the Example class function. The Example instance, which is what you want to refer to, isn't even created yet (though you wish to refer to it).
The reason # refers to the example instance within functions like getText is because javascripts this keyword refers to the object your defined on. Coffeescript is really no different, other then providing you a convenient syntax of referring to the 'this' at the time of a functions definition.
TLDR:
You can't really accomplish what your looking for, and your probably going to have to give up on the idea of a 'private' function on an instance
The best I can see you doing is what you've already described in your comments above
Example.prototype.getText()
Because the two ways you'll be able to refer to this method are through the instance and the Example.prototype (which the function is defined on). Since your method isn't defined on the instance, then you cannot use 'this'. However if you call the method from the prototype, your getText function will fail anyway.
getText: ->
#text
the #text refers to what getText is defined on, and in this context its the prototype (not the instance). And text is undefined on the prototype.
If you want to have this method function the way you expect your probably going to have to make it not 'private'. Javascript/Coffeescript do not have access modifiers like public and private, a private method is really a function defined in a particular scope. In this case that scope doesn't have access to what you want, and the this keyword doesn't refer to what you need.

You're using someFunction = rather than someFunction:. This won't do what you expect.
You're calling someFunction, when in fact you probably want to be calling #someFunction.

In the way you've written your example, 'someFunction' is an anonymous function that has not been bound to anything. So, 'someFunction's 'this' is bound to the global object, which explains your error. You can fix it by using fat arrows to define 'someFunction' and placing 'someFunction' in Example's constructor. This will cause 'someFunction' to be bound to your Example instance. If you were to bind 'someFunction' by using a fat arrow, but leave it outside the constructor as you originally had, 'someFunction' would be bound to the Example constructor, causing 'someFunction' to call a non existent static method --getText-- of Example.
Here's how to get rid of your error:
class Example
constructor: ->
someFunction = =>
alert #getText()
#text = 'Hello world! ;)'
someFunction()
getText: =>
#text
### Instance ###
example = new Example

Related

How does JavaScript assign context to this of event handlers?

After reading related questions #1 , #2
I still haven't found an answer to the following question:
Javascript can set context (i.e. set this) with: bind , call and apply.
But when I'm write an event handler:
document.getElementById('myInput').onclick = function ()
{
alert(this.value)
}
Who/What actually attaches this to the object itself ?
P.S. When using jQuery's :
$("#myInput").bind(function (){...})
there is an internal implementation of (bind, call or apply)
So when I am not using jQuery, who is doing it?
Why, the DOM/JavaScript of course, it's supposed to work that way by W3C.
Event handlers are invoked in the context of a particular object (the current event target) and are provided with the event object itself.
Source
How exactly that happens, we don't know. It's an implementation detail.
All we know is, that the semantics as defined by the W3C are achieved in some way, but which part of the browser does that and and how, that is left up to the browser developers, and they can implement it as they see fit.
To sum up all the discussions:
In general it is JavaScript that binds this to o inside a function call, when o.x() is called.
However, there are some alternative methods of calling functions (like f.apply() and f.call()) that change this behaviour.
onclick is a special case, and the method used to invoke it is unknown and depends on the DOM implementation.
The answers saying it is the DOM are wrong.
This is part of JavaScript itself, as a language. The DOM is ONLY what the name indicates "Document Object Model", which is just how HTML is represented for manipulation by using JavaScript. Objects related to the DOM follow the behavior specified by the standards, but this is implemented by using JS for it. It is the JS engine what does this, in communication with whatever layout engine is being used (Gecko, Trident, WebKit, Presto, etc.). So, if WebKit detects an event, it passes it to the JS engine as the DOM specification indicates so that it can manipulated by the JS programmer (which is why you're even asking about this, because you can work with it).
In other words, if you're writing something in JavaScript, the only engine that understands how to read and execute that is the JS engine. This engine (v8, SpiderMonkey/Jugger/Trace) will receive data from the layout engine and use it so that you can interact with it. Similarly, on the other hand, whenever you run code that affects the layout, the changes will be detected by the layout engine and it will change the layout so that the user perceives the changes: even if the JS code might have initiated this, it is the layout engine that takes care of the layout.
What "this" is when you assign a function to an object, is simply wherever the function belongs to. So, if you assign a function to instance of object a, then said function will refer to a whenever you use "this" inside of it.
If you wanted to think of it in implementation terms, think of it this way:
Whenever you are calling a method, you do so by first telling an instance that you want to call a method with N parameters. This instance calls the method but adds itself into the context, as "this".
In Python this is done more explicitly by making the first parameter of all instance methods the instance itself. Here it is the same, but the instance is passed implicitly instead of explicitly.
Remember, the instance owns the method. When you do "document.getElementById('something')" the call returns an object (which happens to be an HTMLElement object that is part of the DOM, but that's coincidental to how JS interacts with the DOM), and then you are assigning the function as the property click.
Then, whenever you call the method, the JavaScript engine passes the instance by default, just like it passes other variables (like arguments is also generated without you doing anything, also done by the JS engine which implements the ECMAScript standard).
I would recommend checking pages 63:
"The this keyword evaluates to the value of the ThisBinding of the current execution context."
but most importantly, page 68 "Function calls"
http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf
In your example, of an onclick handler it's perfectly straight forward: a DOM element is an object, you're defining the onclick property to be a function. That function effectively becomes a method of that DOMElement/object.When that object is clicked, the function is called as a method of that element, so this points to its owner, the element.
Put simply, the context in which the function executes is the same as the context in which is was created (again: in your example as a method of a DOM Element), unless a reference to a function object is assigned to another object, or when that function object is invoked in another context using call or apply & co.There's a little more to it than this, of course: as I hinted at above, functions are objects themselves and are said to be loosely coupled to their "owner". Well, actually they don't have an owner as such, each time a function is called, its context is determined:
var foo = someObject.someFunction;//reference to method
someObject.someFunction();//this === someObject, context is the object preceding the function
foo();//implies [window].foo(); ==> this is window, except for strict mode
As #wroniasty pointed out, my talking about ownership might be slightly confusing. The thing is, functions are objects, they're not owned by anything. When an object is assigned a method, all that object really owns is a reference to a given function object. When that function is called via that reference, this will point to the object that owned the calling reference. When we apply that to your elem.onclick = function(){}, we see the element only owns a reference to a function expression that was declared in some scope (global, namespace-object, doesn't matter). When the click event fired, that reference will be used to call the handler, thus assigning a reference to the element to this. To clarify:
document.getElementById('foo').onclick = (function()
{//This function returns the actual handler
var that = this;//closure var
console.log(this);//logs window object
//defined in global context
return function(e)//actual handler
{
console.log(this === that);//false
console.log(this);//elem
console.log(that);//window
};
})();//IIFE
So the handler was declared in the global context, and the handler can access its the context it was declared in using that, thanks to closures (but that's another story). The point is, the event references the handler using the onclick property of the element foo. That property is a reference to a function object, so the function object sets its context to whatever object made the call.
I do hope this clears up any confusion I caused with regard to ownership of functions, and perhaps how context in JS is determined.
http://dmitrysoshnikov.com/ecmascript/chapter-3-this/#this-value-in-the-function-code
Basically, it's done by JavaScript internals.
The context is the object calling the function, e.g.
elem.onclick(); // elem === this
However:
func = elem.onclick;
func() // global === this
This really has nothing to do with the DOM as has been mentioned, but how JavaScript is designed to work when you call a function within an object.
Take this as an example:
var myObject = {
id: 1,
onclick: null
}
myObject.onclick = function() {
console.log(this.id);
}
Calling myObject.onclick() will log 1 to the console, which means myObject is its context.
Since onclick is also a property of an object, this will be the parent object, in your case an HTMLElement.
For illustration purposes, although implementations may differ, think of the following function
function f() { alert(this.name); }
as
function f(this) { alert(this.name); }
Imagine this as a secret parameter that you can override with bind, apply and call but that normally gets set to the calling object by the browser.
Example
var a = {},
b = {};
a.name = "John";
b.name = "Tom";
// "this" param added secretly
function printName( ) {
console.log( this.name )
};
a.printName = printName
b.printName = printName;
When calling the printName function the browser sets that "secret" this parameter to the calling function. In the example below this is b and so "Tom" is printed to the console.
printName( ); // global context assumed so this === window
b.printName( ); // this === b and outputs "Tom"
printName.call( a ); //this === a and outputs "John"
Further info here.

referring to prototype method within class variable

I'm having trouble with a JS prototype object I'm working on. What I'm trying to do is define a class-level variable as an object literal, then refer back to one of the class's prototype methods to set a property of the class-level variable, but I'm not getting anywhere. Here's what I am trying to do, in a simplified example:
var foo = function(args)
{
this.name = 'bar';
}
foo.stuff = { barbaz: this.foobarbaz(2) };
foo.prototype.foobarbaz(int)
{
return int;
}
alert(foo.stuff.barbaz); // should alert 2, but I'm missing something
I'm wondering if I'm just misunderstanding the scope of 'this' in this instance, or if this.foobarbaz() is undefined when I assign it to foo.stuff.barbaz.
Is it possible to refer to an object's prototype methods from within a class-level variable like this?
Here is what you need to know:
You should define your method on the prototype like foo.prototype.foobarbaz = function(int) {...}. Your current syntax is not valid.
You're trying to use the method before you define it. If you're expecting function hoisting to work here, that only applies to function declarations, not assignments. Move the assignment of foobarbaz above the first time you use it.
In this function you've provided, this is not foo. Each function has its own value of this (called the function's "context"), set each time the function is invoked. You can see the rules for how a function's context is set in several answers to Understanding Javascript scope with "var that = this".
Instead, here, you'll need to use foo.foobarbaz(2) instead of this.foobarbaz(2), because this is probably window (assuming you call this code not as the method of an object and not in JavaScript's strict mode).

Revealing module pattern naming convention

I'd like to avoid having to remember two names for a method, one for public and one for private access. In that sense, in which case would a script fail if you use same name for both? When would following code fail?
var TestClass = function() {
function showMessage(text) {
$("div").text(text);
}
return {
showMessage: showMessage
};
}();
I've tried it in this fiddle, and it works properly in FF, IE, Chrome, Safari. JSLint has nothing to say about it either.
I've regularly see people naming private method _showMessage or showMessageFn. Is there a good reason for this?
Answer I'm looking for is that it either fails in some situations, may create confusion, or that it's just JavaScript people inventing conventions to seem smart.
This works fine - you're defining a function called showMessage() in the context of your inner function, then assigning it to the showMessage property of your exported object literal.
A property name can be any valid identifier, so showMessage is of course perfectly valid. In your example, function showMessage(text) creates an identifier called showMessage in the inner scope, referencing a function definition. You then create a separate identifier called showMessage as a property name on the object literal, which is assigned the value of the function referenced by the the inner identifier. The fact that both identifiers have the same name is irrelevant as they do not exist in the same scope.
Only problem I can see is that you should wrap the function invocation in parens, otherwise it is not immediately clear to the reader that the function is self-invoking.
So this:
var TestClass = function() {
...
}();
Becomes this:
var TestClass = (function() {
...
}());
The reason private methods are often prefixed with an underscore is simply a widely used convention - it shows that the method is intended to be private (Javascript doesn't support access modifiers, so any property or method that isn't encapsulated in a closure can be accessed from an outer scope). The accepted answer to this StackOverflow quesion sums it up perfectly.
What you are doing here is returning an object that contains the object of the function you defined.
I think that basically it's a way to show whether you are accessing the function in the same scope that it was created or in a different scope.

Is it possible to create a function where [[prototype]] refers to another function

I would like to create function objects (yes, all functions are objects) with some control over the prototypal inheritance, that is, I would like one function to inherit from another.
I can make objects that have prototypal inheritance, and know to set the prototype property of a function performing as a constructor to initialize the [[prototype]] property of the object.
However, when creating a function, I must use the function operator or the Function constructor. I could try to swizzle Function.prototype, but (1) don't know if that is writable, and (2) that just seems quite dangerous [still, I should try doing that].
btw: I only care to do this for V8 within node.JS, so if there are means that work only for that environment, that would be acceptable.
For the record, I have seen this:
Is it possible to create a function with another prototype than Function.prototype?
In V8 (and most other browsers/engines except IE) you can change an object's prototype by setting the __prototype__ __proto__ attribute. Setting the prototype attribute will instead change the prototype that is used to create an object if the function is invoked as a constructor function. This should not be what you want.
Afaik there currently is no standard conform way to directly "subclass" a function (or array for that matter). There's only Object.create, but there is no Function.create or Array.create.
EDIT: I just realized that function objects do not have the __prototype__ attribute and changing / setting it will not turn an object into a function.
I believe though that I just recently watched a talk by Brendan Eich (the creator of JavaScript) in which he talked about Function and Array equivalents of Object.create. And infact, googling for "Function.create brendan eich" reveals the following blog post by Eich in which he talks about his wish to implement Function.create and Array.create.
EDIT 2: Ok, I screwed up. Pretty much. The non-standard attribute is of course __proto__ and not __prototype__. Setting __proto__ works fine for functions with some restrictions, which are:
To be able to call aFunction you must initialize it with an actual function, eg:
var aFunction = function () {};
This is important. Calling a function does not access the prototype chain, so if you define aFunction as an object and simply set the __proto__ attribute, you will not able to call aFunction.
You can now assign any other function to aFunction.__proto__ and reading any members (including methods) will correctly delegate to the prototype chain if the porperty is not found on aFunction itself.
Calling aFunction() will always invoke the function that was originally declared when aFunction was defined and will never invoke aFunction's prototype function. So the body of the function is not subject to inheritence.
Sorry for screwing up first with the name of the attribute. Hope this helps you nevertheless.
I came up with a solution that solves my needs. It is not cross-browser, but can be used cross-browser. My most important use case is as a module for node.JS. In that case, the mechanism of setting __proto__ works just fine, in which case I can call methods on the base function object
f.method(args...);
and it executed by code in the "super" function. Because the method is invoked by the method invocation pattern, "this" is set to the base function object, and so the proper properties are accessed even though the method resides in the "super."
Now for the in-Browser case: when I use my library client-side, I provide a proxy mechanism. Alas, code intended for the browser must be written differently. The invocation is:
f.proxy(methodName, args...);
The proxy method in the base function object is:
f.proxy = function (methodName) {
var p = this.constructor.prototype;
return p.proxy(this, methodName, arguments);
};
The proxy in the "super" object's prototype is:
proxy: function (instance, methodName) {
var args = Array.prototype.splice.apply(arguments, [2]),
method = this[methodName];
return (method) ? method.apply(instance, args) : undefined;
}
I probably should have named this "forward" or some such, but "proxy" is good enough.
Perhaps this mechanism might be useful to someone...
I think I understand what you're trying to do. In short, there's no way to really do it natively. You'd have to access the Function constructor, which for function expressions and definitions (i.e. anything using the 'function' keyword), isn't possible as far as I can tell. You could overwrite Function and just always use new Function([args], string) but I doubt you (or any JS programmer) want to do that.
Your best bet would probably be to send your function expressions to another function that returns the function object with your custom methods dynamically added:
wrapFunc = function(f){
f.customFunc = someCustomFunc;
return f;
}
var myNewFunc = wrapFunc(
function(){
//do something
}
);
myNewFunc.customFunc();

In javascript, how can I tell what object a function is bound to (ie, its 'this') without calling it?

Does anybody know? Couldn't find this question asked before, even though it seems fairly basic.
The context (the this keyword) it's not completely implicit, it can be set and changed explicitly.
For example:
function test () {
alert(this);
}
test.call("Hello world");
The test function is called with a string as the context.
So in conclusion, you cannot know what this is unless you explicitly define it, or you are inside the function.
The same function will see different values of this depending on how it called. See Crockford for details, but there are four cases:
Invoked as a simple function, it is bound to the global/window object.
Invoked as a method on an object, it refers to that object.
Invoked as a constructor via the new keyword, it is the newly instantiated object, which inherits from the object stored in function's own prototype property.
Invoked by its own apply or call method, it is the first argument supplied.
If these cases sound complex, tedious, and error-prone, all the more reason to avoid relying on this outside of methods, where it makes the most sense anyway.

Categories

Resources