Use of Function class in JavaScript - javascript

I have seen usage like var f1=new Function(); but no more than that. Tried to search in Google regarding Function-class but nothing returned what I needed.
What is its significance?
Please suggest me how and when to use it. If possible give me some genuine link to study about it.

Best practice suggest you should never use a base type constructor functions. In a lot of case, use new with a base type will break the usage of typeof.
But, new Function() is valid JavaScript. Just not recommended, and not useful in most cases (var a= function() {} is equivalent).
Not that you can use the Function constructor as an eval call like so new Function('var a = 1; return a + a;'). But this can be dangerous, so use carefully.

There isn't necessarily a beneficial reason to use new Function() since you could simply create a blank function like so:
var f1 = function () {
// my function code here;
};
// calling the function
f1();
Each one will have the prototypes of Function attached to it either way.
new Function() (also new Array(), etc) should typically be avoided since it has to eval.

Technically, there really isn't a difference between these two bits of JavaScript (other answers have covered this):
var f1 = new Function();
and
var f1 = function () { };
What you can do, however, is use Function to check against the types of your variables:
var f1 = 'cat';
console.log(typeof(f1) === typeof(Function)); // false
var f2 = function () { return 'cat'; };
console.log(typeof(f2) === typeof(Function)); // true

Function objects created with the Function constructor are parsed when the function is created. This is less efficient than declaring a function and calling it within your code, because functions declared with the function statement are parsed with the rest of the code.
from MDN

Related

Override js alerts failing [duplicate]

I would like to override a Javascript built-in function with a new version that calls the original (similarly to overriding a method on a class with a version that calls super in many languages). How can I do this?
For example...
window.alert = function(str) {
//do something additional
if(console) console.log(str);
//super.alert(str) // How do I do this bit?
}
Store a reference to the original function in a variable:
(function() {
var _alert = window.alert; // <-- Reference
window.alert = function(str) {
// do something additional
if(console) console.log(str);
//return _alert.apply(this, arguments); // <-- The universal method
_alert(str); // Suits for this case
};
})();
The universal way is <original_func_reference>.apply(this, arguments) - To preserve context and pass all arguments. Usually, the return value of the original method should also be returned.
However, it's known that alert is a void function, takes only one argument, and does not use the this object. So, _alert(str) is sufficient in this case.
Note: IE <= 8 throws an error if you try to overwrite alert, so make sure that you're using window.alert = ... instead of alert = ....
There is no "super". Anyway, create a closure to "keep" around the original function-object.
Note the "self invoking function" that returns a new function-object (that is assigned to the window.alert property). The new function-object returned creates a closure around the variable original which evaluates to the original value of window.alert that was passed in to the "self invoking function".
window.alert = (function (original) {
return function (str) {
//do something additional
if(console) {
console.log(str)
}
original(str)
}
})(window.alert)
However, I believe some browsers may prevent alert and other built-ins from being modified...
Happy coding.
I'm assuming your question is how do you overwrite a built-in and still be able to call it. First off as a disclaimer, you should never overwrite built ins unless you have a good reason for doing it since it will make it impossible to debug/test.
This is how you would do it:
window._alert = window.alert;
window.alert = function(str) {
if(console) console.log(str);
window._alert(str);
}
How to do simple classical inheritance in Javascript:
SuperClass.call(this) // inherit from SuperClass (multiple inheritance yes)
How to override functions:
this.myFunction = this.myFunction.override(
function(){
this.superFunction(); // call the overridden function
}
);
The override function is created like this:
Function.prototype.override = function(func)
{
var superFunction = this;
return function()
{
this.superFunction = superFunction;
return func.apply(this,arguments);
};
};
Works with multiple arguments.
Fails when trying to override undefined or nonfunctions.
Makes "superFunction" a "reserved" word :-)
JavaScript does not use a classical inheritance model. There is a nice article here which describes a way to write your classes so that a similar syntax can be used, but it's not natively supported.
By using proxy object you can do this.
window.alert = new Proxy(window.alert , {
apply: function(target,that,args){
console && console.log(args.join('\n'));
target.apply(that,args)
}})

What does . mean in a JS function when it's used as in .data = [...] [duplicate]

I'm trying to get the principles of doing jQuery-style function chaining straight in my head. By this I mean:
var e = f1('test').f2().f3();
I have gotten one example to work, while another doesn't. I'll post those below. I always want to learn the first principle fundamentals of how something works so that I can build on top of it. Up to now, I've only had a cursory and loose understanding of how chaining works and I'm running into bugs that I can't troubleshoot intelligently.
What I know:
Functions have to return themselves, aka "return this;"
Chainable functions must reside in a parent function, aka in jQuery, .css() is a sub method of jQuery(), hence jQuery().css();
The parent function should either return itself or a new instance of itself.
This example worked:
var one = function(num){
this.oldnum = num;
this.add = function(){
this.oldnum++;
return this;
}
if(this instanceof one){
return this.one;
}else{
return new one(num);
}
}
var test = one(1).add().add();
But this one doesn't:
var gmap = function(){
this.add = function(){
alert('add');
return this;
}
if(this instanceof gmap) {
return this.gmap;
} else{
return new gmap();
}
}
var test = gmap.add();
In JavaScript Functions are first class Objects. When you define a function, it is the constructor for that function object. In other words:
var gmap = function() {
this.add = function() {
alert('add');
return this;
}
this.del = function() {
alert('delete');
return this;
}
if (this instanceof gmap) {
return this.gmap;
} else {
return new gmap();
}
}
var test = new gmap();
test.add().del();
By assigning the new gmap();to the variable test you have now constructed a new object that "inherits" all the properties and methods from the gmap() constructor (class). If you run the snippet above you will see an alert for "add" and "delete".
In your examples above, the "this" refers to the window object, unless you wrap the functions in another function or object.
Chaining is difficult for me to understand at first, at least it was for me, but once I understood it, I realized how powerful of a tool it can be.
Sadly, the direct answer has to be 'no'. Even if you can override the existing methods (which you probably can in many UAs, but I suspect cannot in IE), you'd still be stuck with nasty renames:
HTMLElement.prototype.setAttribute = function(attr) {
HTMLElement.prototype.setAttribute(attr) //uh-oh;
}
The best you could probably get away with is using a different name:
HTMLElement.prototype.setAttr = function(attr) {
HTMLElement.prototype.setAttribute(attr);
return this;
}
To "rewrite" a function, but still be able to use the original version, you must first assign the original function to a different variable. Assume an example object:
function MyObject() { };
MyObject.prototype.func1 = function(a, b) { };
To rewrite func1 for chainability, do this:
MyObject.prototype.std_func1 = MyObject.prototype.func1;
MyObject.prototype.func1 = function(a, b) {
this.std_func1(a, b);
return this;
};
Here's a working example. You just need to employ this technique on all of the standard objects that you feel need chainability.
By the time you do all of this work, you might realize that there are better ways to accomplish what you're trying to do, like using a library that already has chainability built in. *cough* jQuery *cough*
First, let me state that i am explaining this in my own words.
Method chaining is pretty much calling a method of the object being returned by another function/method. for example (using jquery):
$('#demo');
this jquery function selects and returns a jquery object the DOM element with the id demo. if the element was a text node(element), we could chain on a method of the object that was returned. for example:
$('#demo').text('Some Text');
So, as long as a function/method returns an object, you can chain a method of the returned object to the original statement.
As for why the latter don't work, pay attention to where and when the keyword this is used. It is most likely a context issue. When you are calling this, make sure that this is referring to that function object itself, not the window object/global scope.
Hope that helps.
Just call the method as var test = gmap().add();
as gmap is a function not a variable

Javascript function parameter to be used as constructor

I'm trying to do a reusable module, with lesser code. Will something like this work? (Well, not really going to work, it's just an example to give you the idea)
var test = function(foo) {
var bar = new foo(); // The keyword foo is from the parameter
}
The parameter is actually a string. So if I passed "FooBar", a FooBar object will be created.
It's like saying:
var test = function('FooBar') {
var bar = new 'FooBar'();
}
Are there other elegant ways which would fit the solution I'm looking for?
Many thanks!
If foo is a constructor function, then your code will work just fine (I'm curious why you didn't just try it). You can see it work here: http://jsfiddle.net/jfriend00/yT6Vk/.
If you want advise on other/better ways to solve your problem, you'll have to back up and describe more about what you're really trying to do.
There are alternate ways of doing things like this such as factory functions or a single function that examines it's arguments to decide which type of object to create, but without more info on exactly what problem you're trying to solve, we can't really say whether other methods are better/worse than what you already have.
A disadvantage of this method is that you haven't allowed for any arguments to be passed to the constructor.
I would use Douglas Crockford's method
var booze = {
beer:'ale',
wine: 'pinot noir'
}
//test(X)
var createObject = function(o){
function F () {}
F.prototype = o
return new F()
}
var test = function () {
var x = createObject(booze)
return x;
}
test()

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.

Peculiar JavaScript construct: variable of object type in object definition

Okay, I stumbled upon this piece of code..
How come this works? What sort of evil scheme does JavaScript use to resolve variables?
The way I see it, as a C++ kind of guy: the class/object definition contains a non-existent reference to an object of the class being defined. Seriously, how?
(To be honest, I understand partially - I could deduce a strawman concept of how and when JS resolves names.. but maybe this way the question will be of more use to someone else, someday)
Guilty code:
function Sio() {
this.someValue = 5;
this.doStuff = function() {
console.log("look: "+howDoYouResolveThisYouFoulCreature.someValue);
};
}
var howDoYouResolveThisYouFoulCreature = new Sio();
That seems so wrong.
Lots of concepts here, and I'm not sure which one is giving you troubles…
The two most likely ones are new / this and var.
new / this
When you call a function the value of this is determined by the context in which you call it.
If you use the new keyword, you create an instance of the function and make that instance the context.
When you call howDoYouResolveThisYouFoulCreature.doStuff() you are accessing that instance as a global. It would usually make more sense to:
this.doStuff = function() {
console.log("look: "+ this.someValue);
};
Since foo.doStuff() makes foo the context for that invokation of doStuff() (which makes the function reusable between different instances of Sio)
var
Scope in JavaScript is at the function level.
Using var something anywhere inside a function will scope that variable to that function
It is considered good practise to use a single var statement at the top of a function to avoid confusion
Also, the doStuff function is not called before howDoYouResolveThisYouFoulCreature has a value. Until that point all that matters is that the function is syntactically correct, it doesn't matter what type the variable is.
It works because the function() this.doStuff isn't executed before howDoYouResolveThisYouFoulCreature is created. Keep in mind for as many new Sio()'s that you make this will always console.log the howDoYouResolveThisYouFoulCreature.someValue regardless of the variable name that doStuff() is called from.
This works because:
var howDoYouResolveThisYouFoulCreature = new Sio();
... actually resolves into:
var howDoYouResolveThisYouFoulCreature;
howDoYouResolveThisYouFoulCreature = new Sio();
So at the time the function doStuff is assigned, the var is already declared.
Edit: Forget that, I was being foolish. It turns out pimvdb is right, and here's the proof (also on jsfiddle):
function A() {
this.logValue = function() {
if (b === undefined) {
console.log('Wah, wah, wah...');
} else {
console.log(b.someValue);
}
};
}
function B() {
this.someValue = 42;
}
var a = new A();
a.logValue(); // Wah, wah, wah...
var b = new B();
a.logValue(); // 42
So the execution context is the key. When Sio (or, in this case, A) is constructed, it's scoped to where b might, at some point, be defined. The variable isn't resolved until the function is called, at which point it might be defined. Or not. No biggie. :-)

Categories

Resources