Using a method name as the value for an instance variable - javascript

I'm trying to round out my Javascript knowledge. This seems like such a simple thing, yet it's puzzling me.
I have a need to store a method name as a variable. Reducing my test case to the smallest possible size, results in the following:
var someobj = {
someMethod: function() {
console.log('woo');
},
somevariable: this.someMethod
}
There are no callbacks, everything's nice and simple.
console.log(someobj.someMethod);
Returns:
[Function]
Great. But:
console.log(someobj.somevariable)
Returns:
undefined
I was expecting it to return '[Function]'. Why is this?
Thanks.

When declaring objects in JSON - format, there is no this keyword. (well, there is, but i refers to the this of the outer context, for example window in a global context) You cannot access the current object in such a declaration.
You will thus need to set that variable afterwards, something like this:
var someobj = {
someMethod: function() {
console.log('woo');
}
}
someobj.somevariable = someobj.someMethod;

Related

What is it called when a function behaves like a class but doesn't use the class keyword, nor "new" keyword (in Javascript)?

I looked through the suggested links but can't seem to find the term for a function that acts like a class (is it a constructor function? doesn't have that keyword either!) but doesn't use the new keyword, nor class.
I've used both this example's pattern and the class pattern in my code but realized I don't know how to describe the former.
I think this is in part because I learned JS recently, have seen class thrown around a lot, yet looking through my notes of not-ES5,6,7,2018,2020 etc. can't seem to find what var aCounter = counterFunction() is called for the life of me.
I know what the result of what i'm doing is, how to work it, etc. but why no constructor(), no new, no class, no etc.prototype.etc pattern? I know i'm creating an object, calling a method existing Within the object, etc. I believe i'm beginning to ramble.
Lo, an example
const counterFunction = () => {
let val = 0
return {
increment() { val++ },
getVal() { return val }
}
}
which is || can be instantiated (?) like so:
let aCounter = counterFunction() // where i'm getting tripped up
and works like
aCounter.increment() // 1
aCounter.increment() // 2
aCounter.getVal() // 2
I know this is rambling, but help! I think it will make things click more inside once this lexical puzzle piece is put into position!
That is just a function that returns an object literal, which does not act like a class (doesn't have a prototype, and as you pointed out, does not use new, etc).
The functions that are set as the properties of this object (which you store in aCounter) seem to act like class methods because they keep the reference to the variable val alive, but this is not because val is in any way associated with the actual object.
Instead, those functions are closures that keep the reference to the variable alive for as long as the functions themselves are alive.
So to answer your question, what you have described doesn't have any name in particular. It's just a function that returns an object.
Edit:
You asked why there is no constructor() or related syntax in this pattern. Object literals in JavaScript are just mappings of names and values:
const x = { a: 3, b: "hello" };
You do not need a constructor for this, and there is no prototype because it was not instantiated using a constructor. On the other hand, classes and constructor functions are templates for objects that will be created later, and those objects do have a prototype and a constructor because the template contains logic that initializes the object.
class A
{
constructor()
{
this.a = new Date();
this.b = this.a.toString(); // you cannot do this in an object literal
}
}
const x = new A();
Question:
What is it called when a function behaves like a class but doesn't use the class keyword, nor “new” keyword (in Javascript)?
Answer:
It's called a "factory function".
Factory functions usually return a object of a consistent type but are not instances of the factory function itself. Returned objects would rarely inherit from the factory function's prototype property, and calling the factory function does not require new before the function being called.
What you showed there is nothing special. It is just a normal function that has a closure.
Though, you can call it as a type of design pattern.
It looks similar to Revealing Module Pattern where you can separate public property and private property.
Below is an example (not a good one tho):
var counter = function(){
var privateCount = 0;
var privateHistory = [];
return {
getVal: function(){
return privateCount;
},
increment: function(){
privateCount++;
privateHistory.push('+');
return this.getVal();
},
decrement: function(){
privateCount--;
privateHistory.push('-');
return this.getVal();
},
publicHistory: function(){
return privateHistory;
}
}
}
var aCounter = counter();
console.log(aCounter.increment());
console.log(aCounter.decrement());
console.log(aCounter.publicHistory());
Here, you can't directly manipulate the private variables that I don't expose to you.
You can only manipulate those private variables only if I expose the function to you. In this case, the .increment() and .decrement() function.
As you can see, there is no class, no prototype, no constructor.
I can see how you may get tripped up, let's go through your code and explore what's going on:
const counterFunction = () => {
let val = 0
return {
increment() { val++ },
getVal() { return val }
}
}
At this point counterFunction is a variable that points to a function, it's essentially a function name. The ()=>{...} is the function body or function definition and within it the return statement shows that it returns an unnamed object with two property methods.
let aCounter = counterFunction() // where i'm getting tripped up
This is calling your previously defined function, which again returns the object with two methods and assigns it to the variable aCounter. If you did the same thing again for a variable called bCounter they would hold two independent objects.
and works like
aCounter.increment() // 1
aCounter.increment() // 2
aCounter.getVal() // 2
Because the method inside the object refers to a variable outside the scope of the object, but within the function body, a closure is created so that the state of val may be retained. Because the variable is in use, the browser's cleanup process skips over it, so the function is still kept in memory, I believe until the object is destroyed and the function's variable is no longer used.

Putting arrays into custom objects

I am attempting to build my first custom object and it looks something like this:
function URLObject()
{
this.syllables = new Array();
etc...
this.AddtoSyllables = AddtoSyllables;
function AddtoSyllables(AWord)
{
var SylCount = this.syllables.length;
alert("This is SylCount: " + SylCount);
}
}
var myobj = new URLObject();
myobj.AdtoSyllables("text");
The execution of the above code results in the JS engine printing out the following:
This is Sylcount: NAN
-or-
This is SylCount: undefined.
I have looked at information in Head First Javascript, in the Javascript bible, and on various JS websites. All of them cover in exhaustive detail the use of arrays of objects, but none of them discuss arrays within objects.
And yet I am doing something wrong here and I do not know what. Can anyone help?
Here you go:
function URLObject()
{
this.syllables = [];
etc...
}
URLObject.prototype.addToSyllables = function(aWord) {
var SylCount = this.syllables.length;
alert("This is SylCount: " + SylCount);
}
var myobj = new URLObject();
myobj.adtoSyllables("text");
.prototype adds the function declared after it to every object constructed by the constructor function. (in your case every object that was instantiated by new URLObject())
Firstly, the code as posted actually works for me on Chrome and Firefox; so this must depend on the JavaScript engine, or else there's something funky going on.
Update: I suspect what may be confusing you is some separate call to AddtoSyllables (in code you haven't shown us) where suddenly this.syllables is no longer defined. This is where the behavior of this can get confusing. I've created a jsFiddle to hopefully explain how it works a bit better for you.
http://jsfiddle.net/J3tUb/
That said, it is often very possible to write code like this without having to use this (or the prototype) at all. For instance:
function createURLObject() {
// Use closed-over locals instead of attaching properties.
var syllables = new Array();
function AddToSyllables(AWord) {
// Since syllables is closed over, it is accessible here
// (but WON'T be accessible outside this scope).
syllables.push(AWord);
return syllables.length;
}
// Expose whatever functionality you want to be "public"
// in the returned object.
return {
AddToSyllables: AddToSyllables
};
}
var myObj = createURLObject();
myObj.AddToSyllables("text");
It is, of course, valuable to understand JavaScript's quirky (and surprising, to most developers coming from other languages) behavior with respect to this. That said, once you do understand it, I suspect you will find that it can often be avoided altogether.
you need to do this :
function URLObject()
{
var that = this;
that.AddtoSyllables = AddtoSyllables;
function AddtoSyllables(AWord)
etc...
Like this you can add method and attributes to one object.
The issue you are having is that the function AddtoSyllables is not a member function or method of the URLObject. It is just a nested function with no object attachments, so all usages of this will result in returning the dom window object. The correct way of declaring the AddtoSyllables function is this:
function URLObject()
{
//...
}
URLObject.prototype.AddtoSyllables = function (AWord)
{
var SylCount = this.syllables.length;
alert("This is SylCount: " + SylCount);
}
To explain the reasons of the behavior in the question, I'd like to clarify that objects in javascript are treated like a map, dictionary or a key-value pair (use the term what suits you best). Using the syntax x.y = value; is equivalent putting the value value into the map x with key y. Having the code:
this.AddtoSyllables = AddtoSyllables;
function AddtoSyllables(AWord)
{
var SylCount = this.syllables.length;
alert("This is SylCount: " + SylCount);
}
adds the AddtoSyllables function as an entry to the object this points to.
The code
myobj.AdtoSyllables(...)
is equivalent to
myobj["AdtoSyllables"](...) // now a retreiaval operation
or even
var fn = myobj["AdtoSyllables"];
fn (...);
Inside the AdtoSyllables function, this is used. Against common expectations, it is not a pointer to the myobj.
The cause of this is that AddtoSyllables is treated as a static method of the URLObject class (as OOP guys would understand it), or even a loose static function (like in C). To make JS treat it like a member of the URLObject object (an instance method to OOP guys), JS must be told to do so. This is achieved through the URLObject.prototype.AddtoSyllables = .... which equivalents to declaration of an instance method.
From an alternative point of view:
function foo() { /* some code using `this` */ }
var bar = {};
var baz = {};
bar.foo = foo; // same as bar["foo"] = foo;
baz.foo = foo; // same az baz["foo"] = foo;
In the above code, this usages inside foo will neither point to bar, nor baz. At the same time bar.foo will point to the very same instance as baz.foo, for foo is also an object.

jQuery function declaration explanation

I've opened jQuery 1.7.1 library and wanted to study the code, but I've found a that functions are declared in strange way (for me). For example:
show: function() {
//some code here
},
I learned to define function on this way:
function show() {
//some code here
}
Can someone explain me why show function is not written on second way (like in most tutorials on internet)?
This is because it is within an object. Object Literals have their properties defined in this way:
{
name: value,
//OR
'name': value
}
Where value can be nearly anything such as a number, string, function, or even another object. In JavaScript you can also declare anonymous functions and assign them to a variable. In fact, the following declarations have the same effect:
//declares the myFunc1 function
function myFunc1() {}
//declares an anonymous function and assigns it to myFunc2
var myFunc2 = function() {};
//you can now call either like so:
myFunc1();
myFunc2();
So, combining those two concepts if I have an object and I want one of its properties to be a function I would do it like so:
var myObj = {
name: 'My Object',
init: function() {
return 'Initializing!';
},
version: 1.0
};
alert(myObj.init());
You would then get the output: Initializing!. Make sure to check out the great documentation and tutorials on the Mozilla Developer Network, including their JavaScript Tutorial Series
Hope this helps!
Writing it the first way is in essence, setting a function as property of an object.
For example:
// I can create a new empty object
var myObject = {};
// or I can create a new object with a basic property
var myObject = {
color: "blue"
};
// I can also create an object with methods (like jQuery)
var myObject = {
color: "blue",
showColor: function(){
alert(this.color);
}
};
// and you can use the object like this
myObject.showColor(); // calls the showColor method and will alert "blue"
This helps jQuery to encapsulate, namespace, and organize code.
Here are a couple of pretty good write-ups:
Why do you need to invoke an anonymous function on the same line?
http://en.wikibooks.org/wiki/JavaScript/Anonymous_Functions
http://www.evotech.net/blog/2008/07/javascript-object-literals-a-definition/
The first declaration, i.e., show: function, defines show to be a field in an object having type function. The second declares a function named show within the current scope (possibly global?)
they're being described as a js object function. In this case:
var jQuery = {
show: function(){
//some code here
}
}
so you access it like jQuery.show() for example.
I would say Chad's answer is most accurate for in depth research. You should look into them as they can revolutionize how you write js in a very clean way that is much less likely to conflict with other libraries.

"this" in JavaScript

I'm trying to understand the syntax of how to put together a JavaScript function as an object.
Q: Is this the right way to do it?
The reason why I ask is because I'm looking at it in Firebug and I was hoping to be able to drill down and see the value of myVar and myVariable, but instead Firebug only says that "this" is an object Object.
var myObject = {
init: function() {
var myVar = 1;
myObject.myVariable = 2;
console.log('"this" when called as an object: ' + this);
}
}
myObject.init();
Also, what's the funny little syntax to call it directly upon declaration? Something about (), but when I remove the last line and put () at the end of the declaration, I get a syntax error.
This will create a string:
'"this" when called as an object: ' + this
But this is not a string, so its toString() prototype gets called. That's why you only see [object Object].
If you want to have Firebug display the actual object, do a simple console.log(this) or to see the contents directly use console.dir(this).
The "funny little syntax" doesn't really apply here, because you're not really creating a "function object" — that's just an object with a property whose value is a reference to a function object.
However, though it's been done to death on Stackoverflow, you're probably talking about something like this:
var myobject = (function() {
var something = { whatever: "for example" };
return {
init: function() {
this.foo = "hello";
// initialize
},
getSomething: function() { return something.whatever; }
};
})();
Now "myobject" is initialized by a call to an anonymous function, which will be thrown away right after that statement. The closure formed by the function invocation, however, remains alive.
Here is a nice reference for JavaScript object creation

Difference between a constructor and an Object

I definitely need some light on this.
What's the diference between:
var MY_APP = function(){
this.firstMethod = function(){
//something
};
this.secondMethod = function(){
//something
};
};
and
var MY_APP = {
firstKey: function(){
//something
},
secondKey: function(){
//something
}
};
besides the obvious fact that one is a Function and the other an Object, what are the differences in code flow, prototypes, patterns... whatever, and when should we use the first or the second?
I'm so spaced out in this area that i'm not sure if i'm correctly explaining the doubt, but further info can be given if you ask.
The key difference between the two is in how they are intended to be used. A constructor, as its name suggests, is designed to create and set up multiple instances of an object. An object literal on the other hand is one-off, like string and number literals, and used more often as configuration objects or global singletons (e.g. for namespacing).
There are a few subtleties about the first example to note:
When the code is executed, an anonymous function is created and assigned to MY_APP, but nothing else happens. firstMethod and secondMethod don't exist until MY_APP is explicitly called.
Depending on how MY_APP is called, the methods firstMethod and secondMethod will end up in different places:
MY_APP(): Since no context is supplied, the this defaults to window and the methods will become global.
var app1 = new MY_APP(): Due to the new keyword, a new object is created and becomes the default context. this refers to the new object, and the methods will get assigned to the new object, which subsequently gets assigned to app1. However, MY_APP.firstMethod remains undefined.
MY_APP.call(YOUR_APP): This calls my MY_APP but sets the context to be another object, YOUR_APP. The methods will get assigned to YOUR_APP, overriding any properties of YOUR_APP with the same names. This is a really flexible method that allows multiple inheritance or mixins in Javascript.
Constructors also allow another level of flexibility since functions provide closures, while object literals do not. If for example firstMethod and secondMethod rely on a common variable password that is private to the object (cannot be accessed outside the constructor), this can be achieved very simply by doing:
var MY_APP = function(){
var password = "GFHSFG";
this.firstMethod = function(){
// Do something with password
alert(password); // Woops!
};
this.secondMethod = function(){
// Do something else with password
};
};
MY_APP();
alert(password); // undefined
alert(MY_APP.password); // undefined
The first is a function, the second is an object literal. Since Functions in JS are first class objects, a function can have properties on it, just like any other object can.
Typically, if you want to create a "class" that you might be familiar with from classical inheritance languages, you would do something like
function MyClass() {...}
as is documented here http://www.crockford.com/javascript/inheritance.html
To answer the question posed in your edits, you would use them both in different situations. Object literals are used to pass configurations around. A typical usage pattern would be a method that accepts an object literal like so
something.init({
length: 10,
height: 10,
text: 'some text'
});
and so on.
You could use something similar to your first example when creating a namespace. Javascript has some interesting language features in that you can have so-called "self-invoking functions" that are of the form:
var myApp = (function(){
var firstMethod = function() {...}
...
})();
the motivations behind doing something like this are detailed here
http://sparecycles.wordpress.com/2008/06/29/advanced-javascript/
You can also investigate the differences via your favorite javascript debugging console. In firebug and chrome, I did the following:
var ol = {}; ol.prototype;
var fn = function(){}; fn.prototype;
the first line prints undefined, the second returns a prototype with a constructor of 'function'
The constructor can be reused as is, the object literal would need to be repeated or wrapped in a function to be reused.
Example of wrapping the object literal in a function:
function MY_APP() {
return {
firstKey: function(){
//something
},
secondKey: function(){
//something
}
};
}
The object created using the constructor will have it's constructor property set to the constructor function. However, as you used an anonymous function assigned to a variable instead of a named function, the constructor will still be nameless.
Other than that, there isn't really any differences. Both create anonymous functions that are assigned to the properties of the object, so the resulting objects are the same. You can compare this to assigning named functions to the properties, or using prototype functions, both having the difference that each function only exists once instead of being created over and over for each object.
There is some confusion in JavaScript regarding the difference between a function and an object.
In the first case,
var MY_APP = function() { this.v = 7; ... }
or
function MY_APP(x) { this.v = x; ... }
a function is declared, not an object. In MY_APP, this refers to the global object.
Meaning that calling the function MY_APP(7) will assign v globally to the value of 7. (and in your case the function firstMethod would be declared globally).
MY_APP(3); // The global variable v is set to 3
MY_APP(4); // The global variable v is overwritten and set to 4
To use MY_APP as an object, it needs to be instantiated, for instance
var obj1 = new MY_APP(3);
var obj2 = new MY_APP(4);
will have obj1.v to be 3, and obj2.v to be 4.
Note you can also add methods using the prototype keyword (instead of this.firstMethod...)
MY_APP.prototype.firstMethod = function () { ... }
In the second case
var MY_APP = { ... };
an object, one object, is created and its name is MY_APP. The this keywords refers to that object, MY_APP.

Categories

Resources