What is the best way to declare functions within a Javascript class? - javascript

I'm trying to understand the difference between 2 different function declarations in JavaScript.
Consider the following code snippet:
function SomeFunction(){
this.func1 = function(){
}
function func2(){
}
}
What is the difference between the declarations of func1 and func2 above?

In simple language,
fun1 is a property of SomeFunction class holding a reference of anonymous function where func2 is named function.
Property
Here fun1 is property of that SomeFunction class, it means when you create instance of SomeFunction class using new keyword, then only you can access it from outside.
Private Method
Here fun2 will work as private method of class SomeFunction, and will be accessible inside that class only.
Sample
function SomeFunction() {
this.func1 = function() { console.log("in func1") }
function func2() { console.log("in func2") }
}
var obj = new SomeFunction();
obj.func1(); //Accessible
obj.func2(); //Not accessible

This way of declaring functions is called Function Expression. This kind of functions can be called only after definition of the function. Function expressions load only when the interpreter reaches that line of code.
var func1 = function() {
// Code here
}
This way of declaring functions is called Function Declaration. Function declarations load before any code is executed. So it can be called anywhere in the program before it's definition. For reason, read about Hoisting in Javascript
func1 () {
// Code here
}
When defining these inside another function, Function Expression acts as the property of the function and can be accessed using the object of the parent function. Whereas, the scope of Function Declaration is inside the parent function, so it is not accessible from outside the parent function. This is a very important property in Javascript using which we can simulate the Object Oriented Nature.
In brief, Function declaration acts as Private method of a class and Function Expression as Public method.
Here is the working example below to understand more about it.
function SomeFunction(){
this.func1 = function() {
console.log('Public function.')
}
function func2() {
console.log('Private function.')
}
this.func3 = function() {
func2();
}
}
var obj = new SomeFunction();
obj.func1(); // Public Function.
// Can be accessed as it is a Public function
obj.func3(); // Private Function.
// Can be used to access a private function.
obj.func2(); // Error: Uncaught TypeError
// Private function
Hope this helps! :)

function SomeFunction() {
// Function Expression
this.func1 = function() {
}
// Function Declaration
function func2() {
}
}
Update:
Based in your question: What is the best way to declare functions within a Javascript class?
In OOP programming a Class has attributes and methods.
In the following sample code, the Person class contains:
(2) Attributes:
name
country
(1) Method:
showPerson1()
function Person(name, country) {
// Attributes of Person class.
this.name = name;
this.country = country;
// Function Expression:
this.showPerson1 = function() {
var personMessage = "Hi, my name is ";
personMessage += this.name;
personMessage += ". I'm from ";
personMessage += this.country;
personMessage += ".";
return personMessage;
};
// Function Declaration:
function showPerson2() {
var personMessage = "Hi, my name is ";
personMessage += this.name;
personMessage += ". I'm from ";
personMessage += this.country;
personMessage += ".";
return personMessage;
}
}
var person1 = new Person("John", "United States");
console.log(person1.showPerson1()); // Prints: Hi, my name is John. I'm from United States.
console.log(person1.showPerson2()); // Throws an error.
As you can see, you can execute the showPerson1() method because is reference to the Person class by using this keyword and using the Function Expression style.
However, you can't execute showPerson2() method because this function was not created like a reference to the Person class.
You can find more information here.

As far as I know your question revolves around scope. Let's say for a second that you had a main class that called upon functions from other classes. Maybe these other classes have a function called func1 that you needed to use. But wait, you want to use the name func1 in your main class as well without mentioning the global function from the other class. Using this.func1 would allow you to access it as a local function, since .this refers to a local scope.
Basically, it allows him to store the result of the function without declaring a separate variable, which is nice since it's only probably going to be used temporarily and in the context of the function in which it was declared.
Additional Reading (Or in case my analogy falls flat):
http://javascriptissexy.com/understand-javascripts-this-with-clarity-and-master-it/
https://www.w3schools.com/js/js_function_invocation.asp

The func1 is actually a property on SomeFunction so essentially you can do
const someClass = new SomeFunction();
someClass.func1()
But you cannot do
const someClass = new SomeFunction();
someClass.func2()
because it is not attached to that class. However, you can still use the func2 internally in your class SomeFunction but not outside the class.
ES6 provides more clean syntax to understand this.
class SomeClass{
func1(){
//function body
}
}
Hope this helps

Related

What is this code's constructor doing?

I'm not getting what's happening in the below code. Why constructor function is enclosed inside another function and why both constructor and the function in which it is enclosed have given the same name? Also why enclosing function has made to be self invoked?
var Greeter = (function () {
function Greeter(message) {
this.greeting = message;
}
Greeter.prototype.greet = function () {
return "Hello, " + this.greeting;
};
return Greeter;
}());
var greeter;
greeter = new Greeter("world");
console.log(greeter.greet());
In this particular case there's no point in wrapping Greeter in an immediately invoked function (IIFE); Ravindra Thorat is right that rewriting results in (mostly) equivalent behavior.
This construct starts to make sense when you put more stuff inside the anonymous-immediately-executed-function, like the strict mode marker or a private variable (GREETING in example below):
var Greeter = (function () {
"use strict";
const GREETING = "Hello, ";
function Greeter(message) {
this.greeting = message;
}
Greeter.prototype.greet = function () {
return GREETING + this.greeting;
};
return Greeter;
}());
var greeter;
greeter = new Greeter("world");
console.log(greeter.greet());
// console.log(GREETING) // not defined here -- only available inside the anonymous function
Updated to answer a comment:
Note that the value of the outermost variable Greeter is not the outer anonymous (nameless) function itself, but the result of its invocation. Compare:
var Greeter = (function() {...})() // the returned value is assigned to Greeter
var Greeter = (function() {...}) // the anonymous function without parameters is assigned to Greeter
Since the outer anonymous function ends with return Greeter, the value of the outermost Greeter variable is the function Greeter(message) declared inside the IIFE.
Basically everything inside the IIFE is unavailable outside it, except the explicitly returned object (the Greeter(message) constructor in this example).
You can consider the self-invocation function as kind of higher order function, that returns some another function with some configuration.
Okay, what that self-invocation function is doing? It does contain one constructor functions which hold one public property with name "greeting". Input parameter received from constructor function, get assigned to the greeting. After this signature, it's adding some helper function to this constructor function, with the help of prototype, which prints greeting message.
what does it mean by prototype? it's the one of the major pillar of javascript https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/prototype
Well! do we really need a self-invocation function for this? the answer is, nope! we can have this written in a simple way too, just like below,
function Greeter(message) {
this.greeting = message;
}
Greeter.prototype.greet = function () {
return "Hello, " + this.greeting;
};
var greeter;
greeter = new Greeter("world");
console.log(greeter.greet());
That's it! And it will give the exact result as above.
Then why that guy used the self-invocation function for it? I believe, cool design pattern always shines. That guy has a plan to write some factory function kind of thing which would give me a fully configured constructor function. In this case, the self-invocation expression is nothing but the so called factory.
Note: in the original post by you, the outer most Greeter is not a real function, that is a simple variable which holds some function, returned by that self invocation block. You can use any name for that variable.

why is my function "donethingy" considered "not declared"?

i have a question, there is a problem with a function in a program that i was doing in javascript.
The function is supposed to work when you click on a paragraph, but when i click, the javascript console throws this: "Uncaught ReferenceError: donethingy is not defined
Line: 1".
JS:
window.onload = function(){
var thy = document.getElementById("thy");
var commanderIssue = document.getElementById("commanderIssue");
var listado = document.getElementById("thaCosa");
var thyLy = document.getElementsByTagName("p");
var nli;
var thyText;
var inserting = "a";
var commander = "b";
thy.onclick = function(){
inserting = "* " + prompt("Create a new item");
nli = document.createElement("p");
thyText = document.createTextNode(inserting);
nli.appendChild(thyText);
listado.appendChild(nli);
thyLy = document.getElementsByTagName("p");
}
thyLy.onclick = function donethingy(){
// thyLy.textDecoration.overline;
alert("done");
}
commanderIssue.onclick = function(){
alert("this thing is");
}
}
With the syntax you've used, the name donethingy doesn't actually become the name of the function because you are assigning the funciton's code directly to the onclick property of thyLy.
You could do this:
// This is a function declaration that associates a name with the function
function donethingy(){
// thyLy.textDecoration.overline;
alert("done");
}
// Then the function can be referred to or invoked by name
thyLy.onclick = donethingy;
But, when you create and assign the function in one statement, the function effectively becomes anonymous as it is stored and accessible via the property you assigned it to.
The decision to create a function declaration or an anonymous function requires you taking the following into account:
Anonymous functions can't easily be reused.
Anonymous functions can't easily be unit tested.
Named functions may require more memory, but can be reused and can be
easily unit tested.
You do not set variables or onclick properties to functions defined as:
obj.onclick = function <name>() {}
You set to anonymous functions, like you did for commanderIssue.onclick.
Just remove the name of the function to make it anonymous:
thyLy.onclick = function() {
alert("done");
}
It's good to remember that there are two ways of defining functions:
Declarations, which are executed when you invoke them:
function donethingy() { ... }
Expressions, which are executed when variable statements are executed:
thyLy.onclick = function() { ... }

Javascript Class Constructor Call Method

In Java you could call methods to help you do some heavy lifting in the constructor, but javascript requires the method to be defined first, so I'm wondering if there's another way I could go about this or if I'm forced to call the method that does the heavy lifting after it's been defined. I prefer to keep instance functions contained within the Object/Class, and it feels weird that I would have to have the constructor at the very end of the object/class.
function Polynomials(polyString)
{
// instance variables
this.polys = [];
this.left = undefined;
this.right = undefined;
// This does not work because it's not yet declared
this.parseInit(polyString);
// this parses out a string and initializes this.left and this.right
this.parseInit = function(polyString)
{
//Lots of heavy lifting here (many lines of code)
}
// A lot more instance functions defined down here (even more lines of code)
// Is my only option to call it here?
}
Here's what I would do:
var Polynomials = function() {
// let's use a self invoking anonymous function
// so that we can define var / function without polluting namespace
// idea is to build the class then return it, while taking advantage
// of a local scope.
// constructor definition
function Polynomials( value1) (
this.property1 = value1;
instanceCount++;
// here you can use publicMethod1 or parseInit
}
// define all the public methods of your class on its prototype.
Polynomials.prototype = {
publicMethod1 : function() { /* parseInit()... */ },
getInstanceCount : function() ( return instanceCount; }
}
// you can define functions that won't pollute namespace here
// those are functions private to the class (that can't be accessed by inheriting classes)
function parseInit() {
}
// you can define also vars private to the class
// most obvious example is instance count.
var instanceCount = 0;
// return the class-function just built;
return Polynomials;
}();
Remarks:
Rq 1:
prototype functions are public methods available for each instance of the class.
var newInstance = new MyClass();
newInstance.functionDefinedOnPrototype(sameValue);
Rq2:
If you want truly 'private' variable, you have to got this way:
function Constructor() {
var privateProperty=12;
this.functionUsingPrivateProperty = function() {
// here you can use privateProperrty, it's in scope
}
}
Constructor.prototype = {
// here define public methods that uses only public properties
publicMethod1 : function() {
// here privateProperty cannot be reached, it is out of scope.
}
}
personally, I do use only properties (not private vars), and use the '' common convention to notify a property is private. So I can define every public method on the prototype.
After that, anyone using a property prefixed with '' must take his/her responsibility , it seems fair. :-)
For the difference between function fn() {} and var fn= function() {}, google or S.O. for this question, short answer is that function fn() {} gets the function defined and assigned its value in whole scope, when var get the var defined, but its value is only evaluated when code has run the evaluation.
Your 'instance variables' are declared on the 'this' object which if you're looking for a Java equivalent is a bit like making them public. You can declare variables with the var keyword which makes them more like private variables within your constructor function. Then they are subject to 'hoisting' which basically means they are regarded as being declared at the top of your function (or whatever scope they are declared in) even if you write them after the invoking code.
I would create a function declaration and then assign the variable to the function declaration. The reason being that JavaScript will hoist your function declarations.
So you could do this:
function Polynomials(polyString) {
// instance variables
this.polys = [];
this.left = undefined;
this.right = undefined;
// this parses out a string and initializes this.left and this.right
this.parseInit = parseInitFunc;
// This does not work because it's not yet declared
this.parseInit(polyString);
// A lot more instance functions defined down here (even more lines of code)
function parseInitFunc(polyString) {
console.log('executed');
}
// Is my only option to call it here?
}
That way your code stays clean.
jsFiddle

What is a best practice for ensuring "this" context in Javascript?

Here's a sample of a simple Javascript class with a public and private method (fiddle: http://jsfiddle.net/gY4mh/).
function Example() {
function privateFunction() {
// "this" is window when called.
console.log(this);
}
this.publicFunction = function() {
privateFunction();
}
}
ex = new Example;
ex.publicFunction();
Calling the private function from the public one results in "this" being the window object. How should I ensure my private methods are called with the class context and not window? Would this be undesirable?
Using closure. Basically any variable declared in function, remains available to functions inside that function :
var Example = (function() {
function Example() {
var self = this; // variable in function Example
function privateFunction() {
// The variable self is available to this function even after Example returns.
console.log(self);
}
self.publicFunction = function() {
privateFunction();
}
}
return Example;
})();
ex = new Example;
ex.publicFunction();
Another approach is to use "apply" to explicitly set what the methods "this" should be bound to.
function Test() {
this.name = 'test';
this.logName = function() {
console.log(this.name);
}
}
var foo = {name: 'foo'};
var test = new Test();
test.logName()
// => test
test.logName.apply(foo, null);
// => foo
Yet another approach is to use "call":
function Test() {
this.name = 'test';
this.logName = function() {
console.log(this.name);
}
}
var foo = {name: 'foo'};
var test = new Test();
test.logName()
// => test
test.logName.call(foo, null);
// => foo
both "apply" and "call" take the object that you want to bind "this" to as the first argument and an array of arguments to pass in to the method you are calling as the second arg.
It is worth understanding how the value of this in javascript is determined in addition to just having someone tell you a code fix. In javascript, this is determined the following ways:
If you call a function via an object property as in object.method(), then this will be set to the object inside the method.
If you call a function directly without any object reference such as function(), then this will be set to either the global object (window in a browser) or in strict mode, it will be set to undefined.
If you create a new object with the new operator, then the constructor function for that object will be called with the value of this set to the newly created object instance. You can think of this as the same as item 1 above, the object is created and then the constructor method on it is called.
If you call a function with .call() or .apply() as in function.call(xxx), then you can determine exactly what this is set to by what argument you pass to .call() or .apply(). You can read more about .call() here and .apply() here on MDN.
If you use function.bind(xxx) this creates a small stub function that makes sure your function is called with the desired value of this. Internally, this likely just uses .apply(), but it's a shortcut for when you want a single callback function that will have the right value of this when it's called (when you aren't the direct caller of the function).
In a callback function, the caller of the callback function is responsible for determining the desired value of this. For example, in an event handler callback function, the browser generally sets this to be the DOM object that is handling the event.
There's a nice summary of these various methods here on MDN.
So, in your case, you are making a normal function call when you call privateFunction(). So, as expected the value of this is set as in option 2 above.
If you want to explictly set it to the current value of this in your method, then you can do so like this:
var Example = (function() {
function Example() {
function privateFunction() {
// "this" is window when called.
console.log(this);
}
this.publicFunction = function() {
privateFunction.call(this);
}
}
return Example;
})();
ex = new Example;
ex.publicFunction();
Other methods such as using a closure and defined var that = this are best used for the case of callback functions when you are not the caller of the function and thus can't use 1-4. There is no reason to do it that way in your particular case. I would say that using .call() is a better practice. Then, your function can actually use this and can behave like a private method which appears to be the behavior you seek.
I guess most used way to get this done is by simply caching (storing) the value of this in a local context variable
function Example() {
var that = this;
// ...
function privateFunction() {
console.log(that);
}
this.publicFunction = function() {
privateFunction();
}
}
a more convenient way is to invoke Function.prototype.bind to bind a context to a function (forever). However, the only restriction here is that this requires a ES5-ready browser and bound functions are slightly slower.
var privateFunction = function() {
console.log(this);
}.bind(this);
I would say the proper way is to use prototyping since it was after all how Javascript was designed. So:
var Example = function(){
this.prop = 'whatever';
}
Example.prototype.fn_1 = function(){
console.log(this.prop);
return this
}
Example.prototype.fn_2 = function(){
this.prop = 'not whatever';
return this
}
var e = new Example();
e.fn_1() //whatever
e.fn_2().fn_1() //not whatever
Here's a fiddle http://jsfiddle.net/BFm2V/
If you're not using EcmaScript5, I'd recommend using Underscore's (or LoDash's) bind function.
In addition to the other answers given here, if you don't have an ES5-ready browser, you can create your own "permanently-bound function" quite simply with code like so:
function boundFn(thisobj, fn) {
return function() {
fn.apply(thisobj, arguments);
};
}
Then use it like this:
var Example = (function() {
function Example() {
var privateFunction = boundFn(this, function() {
// "this" inside here is the same "this" that was passed to boundFn.
console.log(this);
});
this.publicFunction = function() {
privateFunction();
}
}
return Example;
}()); // I prefer this order of parentheses
VoilĂ  -- this is magically the outer context's this instead of the inner one!
You can even get ES5-like functionality if it's missing in your browser like so (this does nothing if you already have it):
if (!Function.prototype.bind) {
Function.prototype.bind = function (thisobj) {
var that = this;
return function() {
that.apply(thisobj, arguments);
};
}:
}
Then use var yourFunction = function() {}.bind(thisobj); exactly the same way.
ES5-like code that is fully compliant (as possible), checking parameter types and so on, can be found at mozilla Function.prototype.bind. There are some differences that could trip you up if you're doing a few different advanced things with functions, so read up on it at the link if you want to go that route.
I would say assigning self to this is a common technique:
function Example() {
var self = this;
function privateFunction() {
console.log(self);
}
self.publicFunction = function() {
privateFunction();
};
}
Using apply (as others have suggested) also works, though it's a bit more complex in my opinion.
It might be beyond the scope of this question, but I would also recommend considering a different approach to JavaScript where you actually don't use the this keyword at all. A former colleague of mine at ThoughtWorks, Pete Hodgson, wrote a really helpful article, Class-less JavaScript, explaining one way to do this.

Initializing singleton javascript objects using the new operator?

In javascript, what is the difference between:
var singleton = function(){ ... }
and
var singleton = new function(){ ... }
?
Declaring priviliged functions as described by crockford (http://www.crockford.com/javascript/private.html) only works using the latter.
The difference is mainly that in your second example, you are using the Function Expression as a Constructor, the new operator will cause the function to be automatically executed, and the this value inside that function will refer to a newly created object.
If you don't return anything (or you don't return a non-primitive value) from that function, the this value will be returned and assigned to your singleton variable.
Privileged methods can also be used in your second example, a common pattern is use an immediately invoked function expression, creating a closure where the private members are accessible, then you can return an object that contains your public API, e.g.:
var singleton = (function () {
var privateVar = 1;
function privateMethod () {/*...*/}
return { // public API
publicMethod: function () {
// private members are available here
}
};
})();
I think that a privileged function as described by crockford would look like this:
function Test() {
this.privileged = function() {
alert('apple');
}
function anonymous() {
alert('hello');
}
anonymous();
}
t = new Test; // hello
t.privileged(); // apple
// unlike the anonymous function, the privileged function can be accessed and
// modified after its declaration
t.privileged = function() {
alert('orange');
}
t.privileged(); // orange

Categories

Resources