Use of Init in javascript - javascript

Is there a specific use of init() method in javascript?
Consider
var obj = {
init: function(){
return "Hello World";
},
foo: function(){
return "Foo";
}
}
Is there a difference between obj.init() v/s obj.foo()? Is it just a naming convention? Renaming init to main() has no effect. I realize that init is a naming convention that is used to place all of the initialization code for the object. Is that correct?

init has no special meaning in Javascript. It is just an ordinary valid identifier, like foo.
It is often used instead of initialize, because most developers know that init means initialize, and it's shorter to type. If you prefer, there would be no problems with using initialize instead.

Init has no special meaning in javascript. If you're looking for a constructor, in javascript you can call a function with the new keyword. This will create a 'new' this object and pass it to that function as the scope.
function obj(){
this.foo = function() {
return "foo";
}
}
var o = new obj(); // o.foo() returns "foo"
a lot of time people will use an init function to encapsulate the constructor functionality. It is common practice to also write an init function for setting up a plain object when you're not using a constructor.

Related

Call ES5 class method from static method

I want to call an inner function from a static function that was called without an instance, like so:
Foo.Bar = function (options) {
Autodesk.Viewing.Extension.call(this, options);
...
this.innerFunc = function innerFunc(){
...
}
};
Foo.Bar.prototype.constructor =
Foo.Bar;
Foo.Bar.SomeStaticFunc = function () {
innerFunc();
}
Use: Foo.Bar.SomeStaticFunc();.
But I get SomeStaticFunc is not a function.
The example here uses a variable for the class, like var Foo.Bar = function (options) {... but isn't that the same as making an instance of the class like so and calling an inner function?
let x= new Foo.Bar(options);
x.innerFunc();
Is there another way to do this?
PS: I know about ES6 classes but I prefer not to migrate this class to ES6 for now because it isn't totally straight forward.
Well... It seems that you do not know how JavaScript works internally, so here is a quick recap. :)
JavaScript IS an object-oriented language. Object literals are objects, arrays are objects, functions are objects, etc.
JavaScript IS NOT a class-based language. You could say: "Hey, I've seen class and extends keywords in ES6!". Yes, but this is just syntactic sugar. JavaScript is not based on classes like Java, it is based on prototypes.
With ES5 syntax, there are two ways to create what you call a "class":
An object literal
A constructor function
When you use an object literal, your class looks like this:
var myClass = {
myAttribute: "foo",
myMethod: function () {
return "bar";
}
};
When you use a constructor function, your class looks like this:
function MyClass() {
this.myAttribute = "foo";
this.myMethod = function () {
return "bar";
};
}
There are of course differences between these two approaches. With the object literal, you have a sort of Singleton where properties are all static to some extent. With the constructor function, you can produce instances whose properties will be introduced by the this keyword. Example:
var myInstance = new MyClass();
console.log(myInstance);
This instance will have "myAttribute" and "myMethod" in its own properties. This means that these properties are tied to the instance. If you want to call this method, you must do this:
myInstance.myMethod();
So far so good... But there is something wrong with what we did previously. this.myMethod will be created again and again for each instance of MyClass and it is always the same. A better way to handle this is to put it in the prototype so that it can be shared by all instances:
function MyClass() {
this.myAttribute = "foo";
}
MyClass.prototype.myMethod = function () {
return "bar";
};
This is much better, but myMethod is still tied to MyClass instances...
Now I want to create a static method. By definition, our static method will be tied to the class, not to its instances:
MyClass.myStaticMethod = function () {
return "baz";
};
Nice. Here, for the sake of experimentation, I want to do something like this:
MyClass.myStaticMethod = function () {
myMethod();
};
This does not work. Why? In fact, myMethod does not exist in the given scope nor in the outer scope. myMethod has been declared inside another function (the constructor function) and it is not returned, so it is invisible from the outside. Moreover, this function has been put in the prototype of MyClass. This means that it is not available globally, but only on instances of MyClass. When you think about it, it is pretty logical. For instance, when you want to call array methods (methods in Array.prototype), it does not make sense to do that:
push('test');
reverse();
includes('a');
You must call these methods on an array (instance of Array).
[].push('test');
['foo', 'bar', 'baz'].reverse();
['a', 'b'].includes('a');

Javascript: Generating a self executing class that is callable and extendable in window context

some beginner question here but i can't seem to find a working answer for my problem. I want to write a self executing, global javascript class 'foo' whose methods can be called from window context (like window.foo.bar() or just foo.bar() in javascript console), without having to instantiate the class.
At the same time, i want to be able to extend said class with custom functions, e.g.
foo.fn.baz = function() {}
This is how far i have gotten this far:
(function (window) {
var foo = function() {
return this;
};
foo.fn = foo.prototype = {
bar: function (string) {
console.log(string);
}
};
window.foo = foo;
})(window);
When i execute this javascript, the js console now knows the class foo, and i can extend its functions via foo.fn.baz = function(){} but i can't call those functions: foo.bar is undefined.
If i change the code from window.foo = foo; to window.foo = new foo();, then i can call the functions, but i can't extend the class anymore.
How do i do this rigt? Is my code anywhere near the right way to do such a thing? Is it even possible to get both things at the same time?
Anyone with an idea or a hint? Anything would be great.
thanks
foo.bar is undefined
Right. You've put the methods on the prototype property of the function. The object that foo.prototype refers to will get assigned to instances you create via the new operator, as their underlying prototype. So:
var f = new foo();
f.bar();
If you want a singleton (foo is, itself, the one object and you can call foo.bar()), you don't need prototypes at all:
window.foo = {
bar: function(string) {
console.log(string);
}
};
...but as you used the word "class," my guess is that you really do want to create multiple instances using foo, rather than using foo directly, so new foo() would be what you want.
Side note: The overwhelming convention in JavaScript is that if a function is expected to be called via new, it starts with an upper-case letter. So Foo rather than foo.

Can you name an instance the same as its constructor name?

Can you name an instance the same as its constructor name?
var myFunc = new function myFunc(){};
?
As it seems, this replaces the Function Object with the new instance... which means this is a good Singleton.
I haven't seen anyone using this, so I guess, there are downsides to this that I am unaware of...
Any thoughts?
YES...
However, it does look weird that you're creating a named function but never refer to it by name.
The more common pattern(s) I've seen are
function MyClass(){
this.val = 5;
};
MyClass.prototype.getValue = function() {
return this.val;
}
MyClass = new MyClass();
But when people do that I wonder why they don't just use a literal object
var MyClass = {
val: 5,
getValue: function() {
return this.val;
}
}
And I would even prefer to use the module pattern here
var MyClass = (function(){
var val = 5;
return {
getValue: function() {
return val;
}
};
})();
Disclaimer
Now whether the singleton pattern should be used, that's another question (to which the answer is NO if you care about testing, dependency management, maintainability, readability)
http://accu.org/index.php/journals/337
Why implementing a Singleton pattern in Java code is (sometimes) considered an anti-pattern in Java world?
As it seems, this replaces the Function Object with the new instance
No, it does not replace anything. The name of a function expression (that's what you have) is only accessible inside the function itself, not outside of it. It would be exactly the same as if you omit the name:
var myFunc = new function(){};
In general, if you don't want certain symbols accessible, just don't make them global. Define those symbols inside a function and just return whatever you want to make accessible, e.g:
var myobj = (function() {
function Foo() {};
// do whatever
return new Foo();
}());
However, if you just want to create a single object, it is often easier to use an object literal:
var myobj = {};
There is no reason to use a constructor function if you only want to create a single instance from it. If you want to establish inheritance, you can use Object.create [MDN]

Namespaces in JavaScript: do I need to rewrite all my variable and function references?

I am namespacing some JavaScript code, and I want to know if I have rewritten all my function calls and references to global variables correctly. The current code is this:
var x = 10;
function foo() {
console.log('foo');
bar();
},
function bar() {
console.log('bar', x);
}
foo();
I have rewritten it as follows:
var namespace = {
x : 10,
foo: function() {
console.log('foo');
// Is this the correct way to call bar?
this.bar();
},
bar: function() {
// Is this the correct way to refer to x?
console.log('bar', this.x);
}
};
namespace.foo();
Is this correct, i.e. do I need to rewrite all function calls (EDIT: by which I mean all inside the namespace variable) to this.functionname() and all global variables to this.variablename?
If you like, you can make yourself some "real" private variables and methods by incorporating a closure. I favour the module pattern.
var ns = (function () {
var x = 10;
return {
foo: function () {
console.log('foo');
this.bar();
},
bar: function () {
console.log('bar', x);
},
increment: function () {
x++;
}
}
}());
ns.foo();
ns.increment();
ns.foo();
http://jsfiddle.net/DjYue/
No, in some places (code that calls those functions from outside of your namespace object) you would have to call namespace.foo(), namespace.bar(), namespace.varName
Actually, if you use namespace.bar() from the function in the object itself, you get the added benefit that your functions don't depend on context. That is, the following code doesn't work with what you have
var fun = namespace.foo;
fun(); // This would break, since the this value is going to be the global object
I usually don't like to use this from literal objects because of the problem mentioned above. It's definitely a preference, I just prefer to avoid problems with this
No, you shouldn't rewrite to this.funcname() but rather namespace.funcname(). The this keyword is reserved to refer to the current context object (or whatever it's called), meaning that you'd use it within your "namespaced" code to refer to the namespace object.
And generally, it's good to know that you aren't actually working with namespaces as you'd know it from more classical OOP. JavaScript is a prototype-based language, which means that you don't have namespaces - rather, what you're creating is an object containing several properties and methods. As previously mentioned, when you're working with methods of the object, the this keyword refers to the object itself. You'd need a reference to the object when outside of it's context.
Currently, the approach of using objects to contain all of your code as a sort of namespaces and classes in disguise is diminishing in favor of closures which attaches the methods and properties that should be publicly available to a function (which, in JavaScript, is a first class object), and either returns that function or attaches it to the global object. You may also, alternatively, use a function to contain the properties and methods instead of an object.
I disagree with the people who say No to your question. It really depends on what you want to accomplish here. Based the rewritten code, I don't see anything wrong with it. As long as you call namespace.foo(), the execution context of each function should be namespace. Thus, it is not wrong to use this.
There is a situation that invoking the function foo() will not work:
var foo1 = namespace.foo;
foo1();
Although foo1 is same as the function namespace.foo, foo1's execution context has changed. this will refer to window, not namespace.
Their is no need to rewrite that much because you can have more than one reference to a function - a private and a public one.
var namespace = (function() {
var ns = {}; // the 'namespace'
var x = 10;
var foo = // 'private' reference: bar();
ns.foo = // 'public' reference: ns.bar() -> namespace.bar();
function foo() { // the name is optional because it's a function expression
console.log('foo');
bar();
}; // don't forget the semicolon
var bar =
ns.bar =
function() {
console.log('bar', x);
};
return ns; // return the 'namespace'
})();
namespace.foo();
var foo = namespace.foo;
foo();
delete namespace.bar;
// namespace.bar(); // Error
foo(); // bar is called

JavaScript library pattern

I'm trying to figure out the basic pattern for creating a JavaScript library (class). I want to do it in such a way that it doesn't pollute the global namespace with a bunch of junk, but allowing for the class to have instance variables and public methods that modify those instance variables.
Consider the following toy example. I want to make a class Foo. It should contain an instance member, bar, which is a number. There should be a constructor for Foo that takes a number and initializes its instance bar with that number. There should be an instance method that I can call on a Foo object to modify bar. Maybe the code that uses the library looks like this:
var foo1 = new Foo(1);
var foo2 = new Foo(2);
console.log(foo1.bar); // should print "1"
console.log(foo2.bar); // should print "2"
foo2.changeBar(42);
console.log(foo1.bar); // should print "1"
console.log(foo2.bar); // should print "42"
The resultant foo.js would be used by a Web app and therefore included via a script tag in the HTML.
I've done a bit of searching with Google but I have yet to find a single, concise, generic outline of how to design a JavaScript class (used as a library).
(function () {
Foo = function (num) {
this.changeBar(num);
};
var privateMethod = function (x) {
if (this.bar === 999) {
this.bar = x;
}
};
Foo.prototype.changeBar = function (num) {
this.bar = num;
privateMethod.call(this, 1);
};
}());
That is the simplest way of doing it. You don't need to include the definition in a closure, more of a style thing.
Building up on Evan's answer, to showcase some more possibilites. Most normal cases only use some of these though.
(function() {
//When we create variables inside a function they can only be seen by other
// inner functions. Wraping all our code here makes sure noone gets to see
// the private stuff.
//The first opening parenthesis is required for Javascript to parse it
//correctly though
//this is the constructor function
//Note how we set a global variable (Foo) to make it available outside.
Foo = function(num, another_num) {
this.changeBar(num);
//sometimes you will want to make a method that modifies a variable
//that can't be acessed via this.xxx. You can use a closure here for that
//(there are some performance considerations though)
this.baz = function(){
console.log(another_num);
}
//Setting methods "by hand" like this is also useful if you want to
//do multiple inheritance, since you can just set all methods of the
//second class by hand here if you want.
}
//Things on Foo.prototype will be available for all Foo objects,
// via prototypal inheritance magic.
Foo.prototype.changeBar = function(num) {
this.bar = num;
}
var a_secret_variable = 42;
function my_private_function(){
console.log(a_secret_variable);
}
//All private variables can be normaly used (by functions that can see them).
Foo.prototype.use_magic = function(){
my_private_function();
}
}());
//The "fake" function is imediatelly called,
//so in the end all it does is create a inner scope.
The Module Pattern is probably the most popular pattern used today.
var Foo = (function() {
var _thisIsAPrivateVar;
function thisIsAPrivateMethod() {
}
return {
thisIsAPublicMethod : function() {
// can still access the "private" variable and method
}
};
})();

Categories

Resources