JavaScript new Function confusion - javascript

While reading Learning JavaScript 2nd edition, I see a block of code in Chapter 13: Creating Custom JavaScript Objects.
var oneOff = new Function () {
this.variablea = "variablea";
this.method = function () {
return xxx;
}
}
It is said that it is the same as:
var oneOff = new Object();
oneOff.variablea = "variablea";
oneOff.method = function () {...};
But I don't know what new Function () {..} is. Any help is appreciated. Thanks.

When using new function() { /* */ }, you are not creating a new function, but rather an object.
It is just a standard use of new with a constructor function, like in :
var oneInstance = new ConstructorFunction();
function ConstructorFunction() {
this.var1 = 'val1';
this.method1 = function() { } ;
}
The difference is that the constructor is defined right at the time of instantiation, and we omit to call the function, which is legal (although confusing i think).
I find it somehow clearer with some brackets, and making explicit the call to the constructor :
var oneOff = new ( function () {
this.variablea = "variablea";
this.method = function () {
return xxx;
};
} ) () ;
but for creating just one single object, one would rather use the simple object notation :
var oneOff = {
variablea : 'valuea',
method : function () { return xxx; }
}
How do they compare in performances ?
For the new function() {} method, creating the object will require to first create a function, then execute that function within a 'new' context.
On the other hand, object litteral just create ...one object, so it's less time and less garbage created.
On use performances of the two types of objects (time to read/write a property /use a method) it's very hard to say since all javascript interpreters are very complex and very different. When and how do they decide to optimize a part of the code is something you can't really know before benchmarking. - And benchmarking is not an easy task also because of those 'random' optimisations. My bet is that they should be very close in use performance, let us know if you take the time to do some measures.

new function (notice F is lowercase) is one of the many ways of creating an object in Javascript. After the code is interpreted an object will be assigned to oneOff with variablea and method properties.
Another way to achieve this is to use the object literal notation:
var oneOff = {
variablea:"variablea",
method:function () {
return xxx; //this will be undefined
}
}
This works fine if you only need one instance of oneOff however if you need multiple instances of oneOff you can use the function constructor as follows:
function OneOff(){
this.variablea = "variablea";
}
OneOff.prototype.method = function(){
return xxx; //one again undefined
}
var firstOneOff = new OneOff();
var secondOneOff = new OneOff();

Related

Constructor function - in simple namespace - Javascript

In want to define a function-constructor inside a namespace. The way in which I defined the constructor till now was a simple constructor function without NS, combined with prototypal inheritance.
The code looked kind of like:
function mySuperObject() {
var self = this;
self.p1 = "";
self.p2 = "jkejie";
// and others
}
mySuperObject.prototype.func1 = function(){...}
// and others
Introducing namespace:
After reading many articles I decided to start up with a very simple way to define a namespace, maybe the most simplest.
Basically it is just about defining a variable which points to an object-literal and the content is the object (the "mySuperObject" in the code-snippet above). The constructor function is following: mySuperObjectInNS.
The code of the object:
var MYNAMESPACE = {
//some variable outside the object
file : "ConstructorInNamespace_obj.js: ",
//Defining contructor function inside a namespace
mySuperObjectInNS : function(propOne, propTwo){
var self = this;
self.objectName = "mySuperObject";
self.propertyOne = propOne;
self.propertyTwo = propTwo;
self.doSomething = function(){
console.log(file + " doSomething called - function of object");
};
///many more functions and attributes
}
}
MYNAMESPACE.mySuperObjectInNS.prototype.specialFunction = function(){
console.log(file + " specialFunction called - prototypical inheritance defined in file of object, outside of namespace");
};
///many more functions and attributes
In another file it is possible to intantiate the object, as follows:
...
var objOne = new MYNAMESPACE.mySuperObjectInNS("param11", "40");
//following line works just fine
objOne.doSomething();
....
Questions:
It seems to me that this all is about defining an Object-Literal and
I will come into trouble the latest I am trying to define "private"
properties of that object. Is this correct?
Is that mySuperObjectInNS still a constructor function? (For me it
seems it is something else,even if I can intantiate objects from it.
Is is a very bad very bad way of namespacing or is kind of ok?
It seems to me that this all is about defining an Object-Literal and I will come into trouble the latest I am trying to define "private" properties of that object. Is this correct?
"Private properties" have nothing to do with using an object for namespacing. In fact, originally when answering this question, I read that as "private functions" because that would be relevant.
There are lots of ways to do private and semi-private properties in JavaScript, but they relate to how you create the constructor function and the methods it gives the object, not how you expose the constructor function. "Namespace" objects are about how you expose the constructor.
One common pattern for creating "private" properties is to define methods that need to access them within the constructor, and make the "properties" local variables within the constructor (so they aren't really properties at all), like this:
function SuperObject() {
var privateInformation;
this.method = function() {
// This can access `privateInformation`, which is completely
// hidden from outside the constructor
};
}
It doesn't matter at all if you do that within a "namespacing" pattern or on its own.
Private functions, on the other hand, affect the pattern. I'll show both below.
A fairly common variant that provides for private functions is to use a function to create the object, which also gives you the opportunity to create private functions:
var TheNamespace = function() {
function privateFunction() {
}
function SuperObject() {
var privateInformation;
this.method = function() {
// This can access `privateInformation`, which is completely
// hidden from outside the constructor
};
}
SuperObject.prototype.otherMethod = function() {
// Can't access `privateInformation`, but has the advantage
// that the function is shared between instances
};
return {
SuperObject: SuperObject
};
}();
// usage
var s = new TheNamespace.SuperObject();
Is that mySuperObjectInNS still a constructor function? (For me it seems it is something else,even if I can intantiate objects from it.
Yes. A constructor function is any function that expect you to use new with it.
Is is a very bad very bad way of namespacing or is kind of ok?
Using objects as pseudo-namespaces is common practice. You might also consider various asynchronous module definition (AMD) technologies, which largely make "namespace" objects largely unnecessary.
Re your comment:
You defined a self-invoking function....which returns an an object?
It's not a self-invoking function, it's an inline-invoked function, but yes, it's a function that returns an object.
(if so I think parantheses are missing)
No, we don't need any parens that aren't there because the only reason for the outer parens other places you've seen this are to tell the parser that the word function starts an expression rather than declaration; we don't need that in the above because we're already on the right-hand side of an assignment, so there's no ambiguity when function is encountered.
Due to you proposed this way, is it a better way to define the ns?
"Better" is a subjective term. It gives you a scope in which you can define private functions, which you'd asked about.
Whereas I often also saw the option: var = {} | someNSName; What is this all about?
If you have several files that will add things to the "namespace" (as is common), then you frequently see this in each of them:
var TheNamespace = TheNamespace || {};
What that does is declare the variable if it hasn't been declared before, and assign an empty object to it if it doesn't already have one. In the first file that gets loaded, this happens:
The var is processed and creates a new variable, TheNamespace, with the value undefined.
The TheNameSpace = TheNameSpace || {} assignment is processed: Since undefined is falsey, the curiously-powerful || operator results in the new {}, which gets assigned to TheNamespace.
When the next file loads, this happens:
The var is a no-op, because the variable already exists.
The TheNameSpace = TheNameSpace || {} assignment is processed: Since TheNamespace has a non-null object reference, it's truthy, and the curiously-powerful || operator results in a reference to the object TheNamespace refers to.
That is, it has no effect at all.
This is used so you can load the files in any order, or load just one file in isolation.
Here's an example:
thingy.js:
var TheNamespace = TheNamespace || {};
TheNamespace.Nifty = function() {
function privateFunction() {
}
function Nifty() {
var privateInformation;
this.method = function() {
// Can access `privateInformation` here
};
}
Nifty.prototype.otherMethod = function() {
// ...
};
return Nifty;
}();
thingy.js:
var TheNamespace = TheNamespace || {};
TheNamespace.Thingy = function() {
function privateFunction() {
}
function Thingy() {
var privateInformation;
this.method = function() {
// Can access `privateInformation` here
};
}
Thingy.prototype.otherMethod = function() {
// ...
};
return Thingy;
}();
There are lots of variations on that basic pattern, particularly if one file may add multiple things to TheNamespace. Here's one that supports doing so fairly concisely:
var TheNamespace = function(exports) {
function privateFunction() {
}
function Nifty() {
var privateInformation;
this.method = function() {
// Can access `privateInformation` here
};
}
Nifty.prototype.otherMethod = function() {
// ...
};
exports.Nifty = Nifty;
function Thingy() {
var privateInformation;
this.method = function() {
// Can access `privateInformation` here
};
}
Thingy.prototype.otherMethod = function() {
// ...
};
exports.Thingy = Thingy;
}(TheNamespace || {});

what's the difference between these two ways of defining a class/object?

var Foobar = function() {};
Foobar.prototype.clickDetails = function() {
$("#foobar").html("test");
}
and
var Foobar = function () {
return {
clickDetails: function () {
$("#foobar").html("test");
}
};
}();
I'm wondering because the latter is what's existing but I couldn't get it to work with Jasmine and I wrote the first one from scratch. What's the difference between the two?
Because you have the () at the end of your second example (thank you, Bergi!), you're executing that second function immediately and storing the result in Foobar. So your first example creates a function that can be used to create objects via new (which can reuse a single copy of clickDetails), and the second creates a single non-function object.
If you didn't have the () at the end of your second example, e.g.:
var Foobar = function () {
return {
clickDetails: function () {
$("#foobar").html("test");
}
};
}; // <== No () here
...then there would be two differences:
In your first example, there is only one clickDetails function which is shared by all objects created via new Foobar() (via the prototype chain). In your second example, a new clickDetails function is created by every call to Foobar().
In your first example, you create objects via var obj = new Foobar(); (you use the new keyword). In your second, just var obj = Foobar(); (although you can use the new keyword, it has no useful effect, and is misleading).

How to change function inside constructor in JavaScript?

I need to edit the function which locates inside of the constructor.
Example:
some.thing = function() {
this.somefn = function() { // this is the function that I need to fix
...
}
}
But function should be edited not just only for a single object (new obj = some.thing();) but also for any created objects by this constructor.
So is there any way to edit such inner-functions?
Here is a solution based on prototype:
var Something = function () {
this.f = function () {
console.log("Something");
};
};
var Old = Something;
var Something = function () {
Old.apply(this);
this.f = function () {
console.log("New");
};
};
Something.prototype = new Old();
var s = new Something();
s.f(); // prints "New"
The solutions seem just a little too obvious, so I'm wondering if the trouble is that you don't have access to the original code, and you need a more dynamic solution.
If so, one option may be to override the constructor with your own constructor, and have it call the original, and then update the object.
Original code:
some.thing = function() {
this.somefn = function() { // this is the function that I need to fix
...
}
}
Your code:
// cache a reference to the original constructor
var _thing = some.thing;
// your constructor
some.thing = function() {
// invoke the original constructor on the new object.
_thing.apply(this, arguments);
this.somefn = function() { /*your updated function*/ };
};
// maintain inheritance
some.thing.prototype = Object.create(some.thing.prototype);
// make an instance
var theThing = new some.thing();
Now you're getting the benefit of the original constructor and prototype chain, but you're injecting your own function on to the objects being created.
Only trouble may be that the original function you replaced could make special use of the original constructor's variable scope. If that's the case, there would be an issue to resolve.
It would be possible to retain and invoke the original method that you overwrote before invoking yours. Not sure if this situation calls for that or not.
I exactly know your need cause last week I passed through it. I just implemented a complete inheritance model in javascript and as far as I remember, I had a problem with overriding constructors and calling the parent class's ctor when child class is initializing.
So I just solved the problem with modifing some points in my design and it's now working like a charm! (something like C# but in Javascript)
By the way, I don't suggest you to change a method contents this way, but here is a way to do that (I myself did not do that this way and AGIAIN I DO NOT RECOMMEND IT. THERE ARE MANY OTHER WAYS, BUT THIS IS THE EASIEST):
var test = function() { /*InjectionPlace*/ };
eval("var newTest = " + test.toString().replace(
"/*InjectionPlace*/",
"var i = 10; alert(i);"
));
test();
newTest();
Cheers

accessing vars inside a js function

So I have a pseudo class with functions and vars inside of it. For example:
function MyClass()
{
this.a = 0;
this.b = function(c)
{
this.a += c;
}
}
Then, when I go to use it later I'll do this:
var myObject = new MyClass();
myObject.b(3);
myObject.b(5);
but when I do this:
console.log("A: " + myObject.a);
I get:
A: 0
What am I doing wrong?
Here's my actual code. It's split into mutiple files but I'll put up the ones that are relevant:
function SongDatabase() {
this.songs = new Array();
this.loadSongs = function () {
};
this.saveSongs = function () {
};
var _Constructor_ = function () {
var mySong = new Song();
this.songs = new Array(mySong);
};
_Constructor_();
}
function LyriX() {
var songDatabase = new SongDatabase();
//var playlistDatabase = new PlaylistDatabase();
songDatabase.loadSongs();
var sourceList = new ScrollableList();
sourceList.setElement($S.getElement("sourceList"));
var accessoryList = new ScrollableList();
accessoryList.setElement($S.getElement("accessoryList"));
var sourceListClick = function (index) {
$S.log("source click: " + index);
if (index == 0) {
displaySongs();
}
};
sourceList.setClickListener(sourceListClick);
var displaySongs = function () {
$S.log("display songs");
// STACK OVERFLOW LOOK HERE!!! thanks :)
// in debug in chrome songDatabase.songs is a zero length array
accessoryList.loadArray(songDatabase.songs);
};
}
$S.addOnLoadListener(function () {
new LyriX();
});
One issue:
> var _Constructor_ = function () {
> var mySong = new Song();
> this.songs = new Array(mySong);
> };
> _Constructor_();
In the above, when _Constructor_ is called as a function, you don't set its this value so it defaults to the global object (in non-strict mode, or undefined in strict mode). So songs becomes a global variable or throws an error in strict mode.
It seems like fairly useless function anyway, consider:
this.songs = [ new mySong() ];
I see someone's taking the "Java" in JavaScript too literally. :)
A couple things you should know about JavaScript:
In JavaScript, arrays don't work like they do in other languages.
They're a lot more like dictionaries then what you would call an array in C or Java;
they're not significantly more memory efficient, or faster;
no preallocation is done;
there's no offeset, etc, in the low-level implementation.
JavaScript arrays are little more than a convenient (but useful!) structure
for holding order-imperative data.
Arrays can be created using the new Array(length) expression,
or the simple literal expression, [].
Generally, you'll want to use the array literal, [].
Using new Array(length) doesn't really do anything useful;
it sets the initial length property of the array, but that's basically it.
All elements remain undefined.
There are no additional constraints or bounds checking.
You can do a[100] = 'whatever' on an array created by calling var a = new Array(5)
and the interpreter won't bat an eye.
JavaScript uses prototypal inheritance which is significantly different then the
classical inheritance model used in languages like C++ and Java.
With these points in mind, lets examine the following code block:
function SongDatabase() {
this.songs = new Array();
this.loadSongs = function () {
// etc.
};
this.saveSongs = function () {
// etc.
};
var _Constructor_ = function () {
var mySong = new Song();
this.songs = new Array(mySong);
};
_Constructor_();
}
This block of code is probably not doing what you think it's doing.
By initializing the SongDatabase methods inside the SongDatabase() function
you're creating new method functions for every instance of songDatabase.
This may not be a big deal when you're dealing with a couple of dozen of instances,
but if you're dealing with hundreds, the extra memory required can become a problem.
You'll want to use the prototype pattern here, instead (see below).
Your _Constructor_ function isn't doing anything.
var mySong = new Song() creates a new mySong object
local to the _Constructor_ function and not accessible outside of it.
When the _Constructor_ invocation returns,
it's mySong variable is garbage collected (like any other local variable would be).
_Constructor_ is a private function and not a method;
I'm not entirely sure what this in that context will reference.
You may end up creating a songs property on the global object
(but I'd want to test that to be sure).
As I mentioned earlier, when you call Array() with the new operator,
it takes an optional argument that sets the initial length of the array.
In this case, the interpreter will try to coerce mySong into a number
(mySong is not added to the array!);
when that fails it will simply return a new array with length = 0.
Instead, you're better off writing SongDatabase() like so:
function SongDatabase() {
this.songs = [];
// etc.
}
SongDatabase.prototype.loadSongs = function () {
// load songs into `this.songs`
};
SongDatabase.prototype.saveSongs = function () {
// save songs loaded into `this.songs`
};
The prototypal pattern may look strange,
but its probably the best way to handle your use case.
You'll still have direct access to then songs array (which may or may not be important),
and by attaching the loadSongs and saveSongs functions to SongDatabase's prototype
you ensure that those functions are shared.
function MyClass()
{
this.a = 0;
this.b = function(c)
{
this.a += c;
}
}
change a+=c into this.a+=c;
Variables are not bound to "classes", as in other languages. Think of it as an object with properties. A single a just references a variable "a" (not declared with var in the function, so even global in here). You want to update the property "a" of the this object, use this.a instead (the dot operator to access the property). You also may want to read Working with objects.
After your edit (you say you'd been using this.a), it works for me: http://jsfiddle.net/WKuZe/
After you provided us your real code, I noticed this odd structure:
function SongDatabase() {
this.songs = new Array();
// some methods
var _Constructor_ = function () {
var mySong = new Song();
this.songs = new Array(mySong);
};
_Constructor_();
}
A constructor like SongDatabase is (with the new keyword) called with the new instance as this. A normal function is usually called on nothing, i.e. this is undefined or the global object in non-strict mode. See documentation for the this keyword on MDN.
In here, you first initialisize the songDatabases' songs property with an empty array. Then, in the _Constructor_ function, you create an other array with one song but assign it to window.songs, because the function is not called on the songDatabase instance. The same problems may occur in your loadSongs() method. Apart from calling and binding the usual method to provide a "static" reference to the instance object is a scoped variable:
function SongDatabase() {
var that = this; // <== always points to the instance
// some methods
function _Constructor_ () {
var mySong = new Song();
that.songs = new Array(mySong);
// ^^^^
};
_Constructor_();
}
If your _Constructor_ is not a local function, but maybe a interface-adding global function, you might provide the instance (this) as an argument or use _Constructor_.call(this), which allows the use of the this keyword as if _Constructor_ were a "class".

Confusing JavaScript statement: "var x = new this();"

I thought I understood the concept of the JavaScript prototype object, as well as [[proto]] until I saw a few posts regarding class inheritance.
Firstly, "JavaScript OOP - the smart way" at http://amix.dk/blog/viewEntry/19038
See the implementation section:
var parent = new this('no_init');
And also "Simple JavaScript Inheritance" on John Resig's great blog.
var prototype = new this();
What does new this(); actually mean?
This statement makes no sense to me because my understand has been that this points to an object and not a constructor function. I've also tried testing statements in Firebug to figure this one out and all I receive is syntax errors.
My head has gone off into a complete spin.
Could someone please explain this in detail?
In a javascript static function, you can call new this() like so,
var Class = function(){}; // constructor
Class.foo = function(){return this;} // will return the Class function which is also an object
Therefore,
Class.foo = function(){ return new this();} // Will invoke the global Class func as a constructor
This way you get a static factory method. The moral of the story is, not to forget functions are just like any other objects when you are not calling them.
What is confusing you, I think, is just where "this" is really coming from. So bear with me-- here is a very brief explanation that I hope will make it quite clear.
In JavaScript, what "this" refers to within a function is always determined at the time the function is called. When you do:
jimmy.nap();
The nap function (method) runs and receives jimmy as "this".
What objects have references to nap is irrelevant. For example:
var jimmy = {}, billy = {};
jimmy.nap = function(){ alert("zzz"); };
var jimmy_nap = jimmy.nap;
jimmy_nap(); // during this function's execution, this is *NOT* jimmy!
// it is the global object ("window" in browsers), which is given as the
// context ("this") to all functions which are not given another context.
billy.sleep = jimmy.nap;
billy.sleep(); // during this function's excution, this is billy, *NOT* jimmy
jimmy.nap(); //okay, this time, this is jimmy!
In other words, whenever you have:
var some_func = function(arg1, arg2){ /*....*/ };
// let's say obj and other_obj are some objects that came from somewhere or another
obj.some_meth = some_func;
other_obj.some_meth = some_func;
obj.some_meth(2, 3);
other_obj.some_meth(2, 3);
What it's getting "translated" into (not literally-- this is pedagogical, not about how javascript interpreters actually work at all) is something like:
var some_func = function(this, arg1, arg2){ /* ...*/ };
// let's say obj and other_obj are some objects that came from somewhere or another
obj.some_meth = some_func;
other_obj.some_meth = some_func;
obj.some_meth(obj, 2, 3);
other_obj.some_meth(other_obj, 2, 3);
So, notice how extend is used in the example on that page:
UniversityPerson = Person.extend({ /* ... */ });
Pop quiz: When extend runs, what does it think "this" refers to?
Answer: That's right. "Person".
So the puzzling code above really is the same as (in that particular case):
var prototype = new Person('no_init');
Not so mysterious anymore, eh? This is possible because unlike in some languages,
a JavaScript variable-- including "this"-- can hold any value, including a function such as Person.
(There is nothing that makes Person specifically a constructor. Any function can be invoked with the new keyword. If I recall the exact semantics, I think they are that when a function is called with the new keyword, it is automatically given an empty object ({}) as its context ("this") and when the function returns, the return value is that same object unless (maybe?) the function returns something else)
This is a cool question because it speaks to a pretty essential part of JavaScript's neatness or oddness (depending on how you see it).
Does that answer your question? I can clarify if necessary.
AJS.Class effectively* translates this:
var Person = new AJS.Class({
init: function(name) {
this.name = name;
Person.count++;
},
getName: function() {
return this.name;
}
});
Person.count = 0;
into this:
var Person = function (name) {
this.name = name;
Person.count++;
};
Person.prototype = {
getName: function() {
return this.name;
}
};
Person.extend = AJS.Class.prototype.extend;
Person.implement = AJS.Class.prototype.implement;
Person.count = 0;
Therefore, in this case, this in AJS.Class.prototype.extend refers to Person, because:
Person.extend(...);
// is the same as
Person.extend.call(Person, ...);
// is the same as
AJS.Class.prototype.extend.call(Person, ...);
* There are a lot of cases I don't go over; this rewrite is for simplicity in understanding the problem.
Imagine the following situation :
var inner = function () {
var obj = new this;
console.log(obj.myProperty);
};
var f1 = function () {
this.myProperty = "my Property"
}
f1.f2 = inner;
f1.f2();
Here the calling object is itself a function, so this will return a function, and we can instantiate it.
In order to use this()(not this) the outer function(the context) must itself return smth that can be instantiated(another function):
var inner = function () {
var obj = new this();
console.log(obj.myProperty);
};
var f1 = function () {
var func = function () {};
func.myProperty = 'my property';
return func;
};
f1.f2 = inner;
f1.f2();
A simpler code explaination:
class User {
constructor() {
this.name = '';
this.age = '';
}
static getInfo() {
let user = new this();
console.log(user);
}
}
User.getInfo()
Output:
Object {
age: "",
name: ""
}
see this link http://www.quirksmode.org/js/this.html It will tell you about the this keyword, but I am not sure what this() is, may be its some kind of user defined function...... that you are not aware of...
"this" means the context of the function currently running.
The code you are posting surely appears in a function that act as a method for an object.
So the object is the context of the function.
"new this()" will return a clone of the current object after running its constructor function with the passed arguments.
this() refers to the the function that the code is in, but this() would have to be within that function. Calling new this(); within a function would create a never ending loop. Calling it outside of a function would be redundant because there is no function/class set as this().

Categories