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

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.

Related

How can I pass 'this' object to lower function in javascript? [duplicate]

In C++, the language I'm most comfortable with, usually one declares an object like this:
class foo
{
public:
int bar;
int getBar() { return bar; }
}
Calling getBar() works fine (ignoring the fact that bar might be uninitialized). The variable bar within getBar() is in the scope of class foo, so I don't need to say this->bar unless I really need to make it clear that I'm referring to the class' bar instead of, say, a parameter.
Now, I'm trying to get started with OOP in Javascript. So, I look up how to define classes and try the same sort of thing:
function foo()
{
this.bar = 0;
this.getBar = function() { return bar; }
}
And it gives me bar is undefined. Changing the bar to this.bar fixes the issue, but doing that for every variable clutters up my code quite a bit. Is this necessary for every variable? Since I can't find any questions relating to this, it makes me feel like I'm doing something fundamentally wrong.
EDIT: Right, so, from the comments what I'm getting is that this.bar, a property of an object, references something different than bar, a local variable. Can someone say why exactly this is, in terms of scoping and objects, and if there's another way to define an object where this isn't necessary?
JavaScript has no classes class-based object model. It uses the mightier prototypical inheritance, which can mimic classes, but is not suited well for it. Everything is an object, and objects [can] inherit from other objects.
A constructor is just a function that assigns properties to newly created objects. The object (created by a call with the new keyword) can be referenced trough the this keyword (which is local to the function).
A method also is just a function which is called on an object - again with this pointing to the object. At least when that function is invoked as a property of the object, using a member operator (dot, brackets). This causes lots of confusion to newbies, because if you pass around that function (e.g. to an event listener) it is "detached" from the object it was accessed on.
Now where is the inheritance? Instances of a "class" inherit from the same prototype object. Methods are defined as function properties on that object (instead of one function for each instance), the instance on which you call them just inherits that property.
Example:
function Foo() {
this.bar = "foo"; // creating a property on the instance
}
Foo.prototype.foo = 0; // of course you also can define other values to inherit
Foo.prototype.getBar = function() {
// quite useless
return this.bar;
}
var foo = new Foo; // creates an object which inherits from Foo.prototype,
// applies the Foo constructor on it and assigns it to the var
foo.getBar(); // "foo" - the inherited function is applied on the object and
// returns its "bar" property
foo.bar; // "foo" - we could have done this easier.
foo[foo.bar]; // 0 - access the "foo" property, which is inherited
foo.foo = 1; // and now overwrite it by creating an own property of foo
foo[foo.getBar()]; // 1 - gets the overwritten property value. Notice that
(new Foo).foo; // is still 0
So, we did only use properties of that object and are happy with it. But all of them are "public", and can be overwritten/changed/deleted! If that doesn't matter you, you're lucky. You can indicate "privateness" of properties by prefixing their names with underscores, but that's only a hint to other developers and may not be obeyed (especially in error).
So, clever minds have found a solution that uses the constructor function as a closure, allowing the creating of private "attributes". Every execution of a javascript function creates a new variable environment for local variables, which may get garbage collected once the execution has finished. Every function that is declared inside that scope also has access to these variables, and as long as those functions could be called (e.g. by an event listener) the environment must persist. So, by exporting locally defined functions from your constructor you preserve that variable environment with local variables that can only be accessed by these functions.
Let's see it in action:
function Foo() {
var bar = "foo"; // a local variable
this.getBar = function getter() {
return bar; // accesses the local variable
}; // the assignment to a property makes it available to outside
}
var foo = new Foo; // an object with one method, inheriting from a [currently] empty prototype
foo.getBar(); // "foo" - receives us the value of the "bar" variable in the constructor
This getter function, which is defined inside the constructor, is now called a "privileged method" as it has access to the "private" (local) "attributes" (variables). The value of bar will never change. You also could declare a setter function for it, of course, and with that you might add some validation etc.
Notice that the methods on the prototype object do not have access to the local variables of the constructor, yet they might use the privileged methods. Let's add one:
Foo.prototype.getFooBar = function() {
return this.getBar() + "bar"; // access the "getBar" function on "this" instance
}
// the inheritance is dynamic, so we can use it on our existing foo object
foo.getFooBar(); // "foobar" - concatenated the "bar" value with a custom suffix
So, you can combine both approaches. Notice that the privileged methods need more memory, as you create distinct function objects with different scope chains (yet the same code). If you are going to create incredibly huge amounts of instances, you should define methods only on the prototype.
It gets even a little more complicated when you are setting up inheritance from one "class" to another - basically you have to make the child prototype object inherit from the parent one, and apply the parent constructor on child instances to create the "private attributes". Have a look at Correct javascript inheritance, Private variables in inherited prototypes, Define Private field Members and Inheritance in JAVASCRIPT module pattern and How to implement inheritance in JS Revealing prototype pattern?
Explicitly saying this.foo means (as you've understood well) that you're interested about the property foo of the current object referenced by this. So if you use: this.foo = 'bar'; you're going to set the property foo of the current object referenced by this equals to bar.
The this keyword in JavaScript doesn't always mean the same thing like in C++. Here I can give you an example:
function Person(name) {
this.name = name;
console.log(this); //Developer {language: "js", name: "foo"} if called by Developer
}
function Developer(name, language) {
this.language = language;
Person.call(this, name);
}
var dev = new Developer('foo', 'js');
In the example above we're calling the function Person with the context of the function Developer so this is referencing to the object which will be created by Developer. As you might see from the console.log result this is comes from Developer. With the first argument of the method call we specify the context with which the function will be called.
If you don't use this simply the property you've created will be a local variable. As you might know JavaScript have functional scope so that's why the variable will be local, visible only for the function where it's declared (and of course all it's child functions which are declared inside the parent). Here is an example:
function foo() {
var bar = 'foobar';
this.getBar = function () {
return bar;
}
}
var f = new foo();
console.log(f.getBar()); //'foobar'
This is true when you use the var keyword. This means that you're defining bar as local variable if you forget var unfortunately bar will became global.
function foo() {
bar = 'foobar';
this.getBar = function () {
return bar;
}
}
var f = new foo();
console.log(window.bar); //'foobar'
Exactly the local scope can help you to achieve privacy and encapsulation which are one of the greatest benefits of OOP.
Real world example:
function ShoppingCart() {
var items = [];
this.getPrice = function () {
var total = 0;
for (var i = 0; i < items.length; i += 1) {
total += items[i].price;
}
return total;
}
this.addItem = function (item) {
items.push(item);
}
this.checkOut = function () {
var serializedItems = JSON.strigify(items);
//send request to the server...
}
}
var cart = new ShoppingCart();
cart.addItem({ price: 10, type: 'T-shirt' });
cart.addItem({ price: 20, type: 'Pants' });
console.log(cart.getPrice()); //30
One more example of the benefits of the JavaScript scope is the Module Pattern.
In Module Pattern you can simulate privacy using the local functional scope of JavaScript. With this approach you can have both private properties and methods. Here is an example:
var module = (function {
var privateProperty = 42;
function privateMethod() {
console.log('I\'m private');
}
return {
publicMethod: function () {
console.log('I\'m public!');
console.log('I\'ll call a private method!');
privateMethod();
},
publicProperty: 1.68,
getPrivateProperty: function () {
return privateProperty;
},
usePublicProperty: function () {
console.log('I\'ll get a public property...' + this.publicProperty);
}
}
}());
module.privateMethod(); //TypeError
module.publicProperty(); //1.68
module.usePublicProperty(); //I'll get a public property...1.68
module.getPrivateProperty(); //42
module.publicMethod();
/*
* I'm public!
* I'll call a private method!
* I'm private
*/
There's a little strange syntax with the parentless wrapping the anonymous functions but forget it for the moment (it's just executing the function after it's being initialized). The functionality can be saw from the example of usage but the benefits are connected mainly of providing a simple public interface which does not engages you with all implementation details. For more detailed explanation of the pattern you can see the link I've put above.
I hope that with this :-) information I helped you to understand few basic topics of JavaScript.
function Foo() {
this.bar = 0;
this.getBar = function () { return this.bar };
}
When you call the function above with the new keyword - like this...
var foo = new Foo();
... - a few things happen:
1) an object is created
2) the function is executed with the this keyword referencing that object.
3) that object is returned.
foo, then, becomes this object:
{
bar: 0,
getBar: function () { return this.bar; }
};
Why not, then, just do this:
var foo = {
bar: 0,
getBar: function () { return this.bar; }
};
You would, if it's just that one simple object.
But creating an object with a constructor (that's how it's called) gives us a big advantage in creating multiple of the "same" objects.
See, in javascript, all functions are created with a prototype property [an object], and all objects created with that function (by calling it with the new keyword) are linked to that prototype object. This is why it's so cool - you can store all common methods (and properties, if you wanted to) in the prototype object, and save a lot of memory. This is how it works:
function Foo( bar, bob ) {
this.bar = bar;
this.bob = bob;
}
Foo.prototype.calculate = function () {
// 'this' points not to the 'prototype' object
// as you could've expect, but to the objects
// created by calling Foo with the new keyword.
// This is what makes it work.
return this.bar - this.bob;
};
var foo1 = new Foo(9, 5);
var foo2 = new Foo(13, 3);
var result1 = foo1.calculate();
var result2 = foo2.calculate();
console.log(result1); //logs 4
console.log(result2); //logs 10
That's it!
To get closer to OOP in JavaScript, you might want to take a look into a Module design pattern (for instance, described here).
Based on the closure effect, this pattern allows emulating private properties in your objects.
With 'private' properties you can reference them directly by its identifier (i.e., no this keyword as in constructors).
But anyway, closures and design patterns in JS - an advanced topic. So, get familiar with basics (also explained in the book mentioned before).
In javascript this always refers to the owner object of the function. For example, if you define your function foo() in a page, then owner is the javascript object windows; or if you define the foo() on html element <body>, then the owner is the html element body; and likewise if you define the function onclick of element <a>, then the owner is the anchor.
In your case, you are assigning a property bar to the 'owner' object at the begining and trying to return the local variable bar.
Since you never defined any local varialbe bar, it is giving you as bar is undefined.
Ideally your code should have defined the variable as var bar; if you want to return the value zero.
this is like a public access modifier of objects(variables or functions), while var is the private access modifier
Example
var x = {};
x.hello = function(){
var k = 'Hello World';
this.m = 'Hello JavaScript';
}
var t = new x.hello();
console.log(t.k); //undefined
console.log(t.m); //Hello JavaScript

JavaScript classes and 'this'

class Aa {
methodA() {
console.log('welcome to method a')
}
methodB() {
console.log('welcome to method b')
// methodA() // Fails!! Uncaught ReferenceError: methodA is not defined
this.methodA() // Works because of this.
}
}
let myclass = new Aa()
myclass.methodB()
What is the best way to concisely explain why you need to use 'this' when calling another method of the class that you are already in?
Intuition might say, well if JS knows that I'm using a method of a class, then it knows about that class...because I'm using it's method.....so why can't it find another method of that same class without me telling it...yeah 'this' same place!
By way of contrast, functions can do it with no problem:
function a() {
console.log('welcome to function a')
}
function b() {
console.log('welcome to function b')
a() // works without any sort of 'scope help'
}
b()
I want to be able to explain it without getting people distracted with needing to know the deepest reasons for it. If possible, ha!
Part of me just wants to say, "That's how JS classes work. You gotta 'this'-ify things."
In order to understand why we need to explicitly reference this in Javascript classes, we first need to understand what the this reference points to in ordinary functions.
This
In Javascript the this keyword is always a reference to the object that called the function.
Consider the following:
const obj1 = {
foo() { console.log(this); }
}
obj1.foo(); // "this" will reference "obj1"
Nothing strange here, this is a reference to the object where it was defined obj1.
Now think about what would happen if we took the function foo and "removed" it from the object. Since this is a reference to the object that called the function, what should this be if the function doesn't belong to an object?
const obj1 = {
foo() { console.log(this); }
}
const foo = obj1.foo;
foo(); // "this" will reference "window"
This is were things start to become strange, this is actually a reference to the global object. This is because everything in Javascript is an object, even the root level of a file. In the browser this global object is called the window object.
Now consider what happens if we reattache the method to another object?
const obj1 = {
foo() { console.log(this); }
}
const foo = obj1.foo;
const obj2 = {};
obj2.foo = foo;
obj2.foo(); // "this" will reference "obj2"
The same rules apply here, since the function now belongs to an object again the this reference points to obj2.
Classes
Fist of all Javascript doesn't actually have classes. A js class in just a different way of writing a prototype.
Lets start by writing a simple class.
class Foo {
constructor() { console.log("I'm a Class constructor") }
log() { console.log("I'm a Class method") }
}
const obj1 = new Foo(); // I'm a Class constructor
obj1.log(); // I'm a Class method
Now lets write the same "class" as a prototype.
function Bar() {
console.log("I'm a Prototype constructor")
}
Bar.prototype = {
log() {
console.log("I'm a Prototype method")
}
}
const obj2 = new Bar(); // I'm a Prototype constructor
obj2.log(); // I'm a Prototype method
These two ways of writing inheritance (classes & prototypes) are the same thing in Javascript.
So as we can more clearly see in the prototype implementation the "class methods" are actually just an object assigned to the prototype of a function.
Now that we know about this and about classes / prototypes we can see that a class method is actually just a function on an object and that this refers to the the object that called the function. So if we want to reference another function on the same object we should do so by referencing it through the this reference.
class Aa {
methodA() {
console.log('welcome to method a')
}
methodB() {
console.log('welcome to method b')
this.methodA()
}
}
const myclass = new Aa()
myclass.methodB()
It is confusing mostly because Javascript has a long history of trying to fit the square peg of prototypes into the round hole of classes. A lot of things that make sense in traditional object-oriented languages only lead to confusion in javascript.
Your (very reasonable) intuition goes off the rails here:
Intuition might say, well if JS knows that I'm using a method of a class, then it knows about that class...because I'm using it's method
methodA() and methodA() are just functions. They don't know anything about where they were defined. What they know is how they were called. this is the key to tying how the function is called to the rest of the class. Consider this example:
class Aa {
methodA() {console.log('welcome to method a')}
methodB() {
console.log('welcome to method b')
this.methodA() // Works because of this.
}
}
let obj = {
methodA() { console.log("welcome to imposter A")}
}
let myclass = new Aa()
obj.methodB = myclass.methodB // take a reference to methodB and add it a different obj
console.log("Same?",obj.methodB === myclass.methodB)
// identical function but it has no idea
// it "belongs" to myclass. Called from a different context
// it acts like a normal function (because it is)
obj.methodB()
The function obj.methodB doesn't know it belongs to class Aa. The only thing the relates it to the class is the way it's called and the way it's called determines the value of this. So this (and the prototype chain) is the glue that holds the whole scheme together.

javascript .prototype for object function extensions

--
Hello SO,
Hoping for some minor guidance on the issue of .prototype.
I've gone through all the answers in SO and they did not seem to cover this specific question, or maybe they did but I did not understood it like that.
The question at hand (and code)
function foo(){};
foo.prototype.type = 'foo';
function bar()
{
this.prototype = foo.prototype;
}
test = new bar();
console.log(test.type); // type is undefined
The question
From what I understand, the request for the type had to cascade up the prototype chain until it found the foo prototype, This did not happen, Obviously I'm understanding something wrong - Why is type undefined?
I'm basically trying to find a way to extend a function object so that
new foo() - return a foo object
new bar() - return a bar object that has all the methods and properties of foo.
I appreciate any help or reference I can get!
Well, when you do this:
function bar()
{
this.prototype = foo.prototype;
}
you are not changing the bar object prototype but assigning a new property to the bar object called prototype, which has the foo object prototype, basically: { type: 'foo' }.
then:
test = new bar();
console.log(test.type); // type is undefined
of course is undefined! you never define it, you just define the prototype property
console.log(test.prototype); // I have surprises for you
I think you want somethink like inheritance. I suggest the Crockford way of inheritance:
Function.prototype.inherits = function (Parent) {
this.prototype = new Parent();
return this;
};
Then, just do:
bar.inherits(foo);
Now,
test = new bar();
console.log(test.type); // foo!
Hope this helps
Thanks for the comments and replies, to extend lante's answer to what I think is fully explaining the situation.
A JavaScript function is of course an object, When you instantiate a new instance of a function object, The created object receives the prototype of that function.
for instance,
var Foo = fn() {
this.ok= 'this is okay';
}
var Bar = fn(){};
Bar.prototype = new Foo(); // Bar.prototype is now a regular object, nothing fancy.
//for all intents and purposes, this is exactly like doing this :
Bar.prototype = {ok : 'this is okay'}; //just assigns an object, reduntent
var test = new Bar(); //new Bar instance
console.log(test.ok); //prints 'bar'
What's the magic?
test has no ok property, But when it's being called it chains up to the function object's prototype and tries to find it there, if it can't, it keeps moving up until it reaches the end.
Thanks again for all the answers

fn.call(this) versus fn() when defining a CommonJS module

It's common to see CommonJS modules defined using the following idiom:
(function() {
var logThis = function() { console.log(this); }
module.exports = logThis;
}).call(this);
Underscore.js, for example, does this.
I just spend half an hour discussing with a colleague why they invoke the closure with call(this). This will cause the value of this inside the closure to be inherited from the caller, rather than being set to the global object. However, when I tested this in Node.js, the value of this inside the module was always the global object, even when I loaded and ran it like this:
var bar = {};
bar.foo = function() { var foo = require("./foo"); foo(); }
I was really expecting to see the bar object in the console, but actually I see the global object. It then occurred to me that this might be because modules like Underscore.js are also used in a web context. But in that case it would be loaded with a <script> tag so this will always be equal to the global object anyway.
What gives? I'm sure there is a reason for using this construct but I can't see the practical difference in this particular case whether the module is being used in Node.js or in a webpage.
Update: Just to clarify, I can think of a number of cases where this could make a difference. For example, if I say:
var bar = {}
var foo = require("./foo");
bar.foo = foo;
bar.foo();
(Thanks to #Pointy for correcting my original example.)
I would expect the closure in the module to be evaluated when require() is called, which means that the value of this inside it would be bound to the global object, which would be written to the console even though foo() is then invoked as a member of the "bar" object. However, I am seeing the "bar" object in the console even in this example. I guess that this is not being bound to the closure as I expected?
In a nutshell, I'm looking for one example where a module like Underscore.js will have different behavior due to being wrapped in a closure invoked with fn.call(this) instead of just fn(), either in Node.js or in a web page.
Your call to "foo" inside "bar.foo" is made without any context, so the global context is used. The fact that it's inside a function where this refers to "bar" is not relevant; that's just not how JavaScript works. The only thing that matters is how the function is invoked, not where it's invoked, in other words.
If "bar.foo" looked like this:
bar.foo = function() { require("./foo"); foo.call(this); }
then you'd see "bar" in the console. Or, you could do this:
var bar = {};
require("./foo");
bar.foo = foo;
Then calling bar.foo() would also log the "bar" object. (Does that really work in Node? That is, I thought require() returned an object, and that it didn't just leave things in the global scope. I'm a rank novice at Node however.)
edit — OK thanks for updating. Thus, my example would be corrected as follows. First, I think that your module should look like this:
(function() {
var logThis = function() { console.log(this); }
module.exports.logThis = logThis;
}).call(this);
That is, I think that you want to explort the "logThis" function, so it needs to be bound to the "exports" object as a named property.
Then:
var bar = {};
var foo = require("./foo");
// At this point, foo.logThis is the function
bar.foo = foo.logThis;
// Now the "foo" property of "bar" is a reference to the same function
bar.foo(); // logs the "bar" object
var fee = { fie: foo.logThis };
fee.fie(); // logs the "fee" object

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