20

I picked up some code and I am just getting to understand the new Function();. Going through jslint the new Function(); was highlighted as unexpected. I started to experiment with it doing the following.

var func = new Function();
func.property = "some property";
return func;

A replacement.

var func = new function(){
this.property = "some property";
}
return func;

Both work and the second one is neglected by js-lint.

Am I doing anything spectacular here, or is this exactly the same? Is it syntactical correct to use new Function(); like this?

Original code excerpt is attached.

 var $ = (function() {

   function doCSS(prop, val) {
     var isSet = Boolean(val),
       action = CSSStyleDeclaration.prototype.setProperty,
       args = arguments;
     if (isSet) {
       this.each(function(node, i) {
         action.apply(node.style, args);
       });
       return this;
     } else if (typeof(prop) === 'object') {
       this.each(function(node, i) {
         Object.keys(prop).forEach(function(property) {
           node.style[property] = prop[property];
         });
       });
       return this;
     } else {
       return this.nodes[0].style[prop];
     }
   }



   // chaining of methods
   return (function(selector, context) {
     var q = new Function();
     q.selector = selector;
     q.context = context || document;
     q.nodeList = q.context.querySelectorAll(selector);
     q.each = function(action) {
       [].forEach.call(q.nodeList, function(item, i) {
         action(item, i);
       });
       return this;
     };
     q.click = function(action) {
       [].forEach.call(q.nodeList, function(item, i) {
         item.addEventListener("click", action, false);
       });
       return this;
     };
     q.toString = function() {
       return q.selector;
     };
     q.css = function(prop, val) {
       return doCSS.call(this, prop, val);
     };


     return q;


   });
 })

Is any of these two wrong in syntax?

EDIT After getting some of the great advice I adapted the code to the following:

var $ = (function($) {

  function doCSS(prop, val) {
    var isSet = Boolean(val),
      action = CSSStyleDeclaration.prototype.setProperty,
      args = arguments;
    if (isSet) {
      this.each(function(node, i) {
        action.apply(node.style, args);
      });
      return this;
    } else if (typeof(prop) === 'object') {
      this.each(function(node, i) {
        Object.keys(prop).forEach(function(property) {
          node.style[property] = prop[property];
        });
      });
      return this;
    } else {
      return this.nodes[0].style[prop];
    }
  }

  // chaining of methods
  return (function(selector, context) {
    var element = context || document;
    var q = {
      selector: selector,
      nodeList: element.querySelectorAll(selector),
      each: function(action) {
        [].forEach.call(this.nodeList, function(item, i) {
          action(item, i);
        });
        return this;
      },
      click: function(action) {
        [].forEach.call(this.nodeList, function(item, i) {
          item.addEventListener("click", action, false);
        });
        return this;
      },
      toString: function() {
        return selector;
      },
      css: function(prop, val) {
        return doCSS.call(this, prop, val);
      },

    }

    return q;

  });


})($);

$("#myElement").css({
  background: "blue",
  color: "#fff"
});
<div id="myElement">Say Hi</div>

It works just fine and looks a lot cleaner. JS Lint is nice to me and I can tackle the next issue.

Daniel
  • 4,816
  • 3
  • 27
  • 31
  • 2
    Why do you even use `Function` instead of an object `{}` in your code? – zerkms Oct 17 '16 at 22:35
  • 1
    It is syntactically correct of course, or you'd get a syntax error when loading the file. JSLint flags it because Crockford didn't think you should create functions like that. Also, I'm with @zerkms; neither of them are doing anything that that you couldn't do with `var q = {};`. – Heretic Monkey Oct 17 '16 at 22:36
  • @zerkms - What I understand is that the Function is attached to each instance when the `$(selector, context)` is called. Each object created will gain its own executable methods. – Daniel Oct 17 '16 at 22:38
  • @MikeMcCaughan - I'll give that a spin ... – Daniel Oct 17 '16 at 22:39
  • 2
    they do something different. `typeof (new Function) === "function"`, `typeof (new function(){}) === "object"`. – chiliNUT Oct 17 '16 at 22:40
  • 1
    @Daniel for the code you provided I don't see how `var q = new Function();` behaviour would be different to `var q = {};` – zerkms Oct 17 '16 at 22:40
  • 3
    **Never ever** [use `new function`](http://stackoverflow.com/q/10406552/1048572)! – Bergi Oct 17 '16 at 22:43
  • only problem with `new Function` is that in order to give it any code, you'd have to pass it in as a string which makes it harder to statically analyse/optimise – Dan Oct 17 '16 at 22:44
  • 2
    There is so much wrong with both syntaxes. What are you actually trying to do? What result do you need? Is `func` supposed to be a function? If yes, what should it do when called? And yes, you really could need a [codereview.SE] on your original code (at least from what you've shown as an excerpt). – Bergi Oct 17 '16 at 22:44
  • @Bergi - Since you asked, I changed the snippet. This is how it came from a YouTube source. – Daniel Oct 17 '16 at 22:53
  • @Daniel Really? Wow, that is horrible code. Can you link the source, please? – Bergi Oct 17 '16 at 22:55
  • 1
    Looks like someone took a stab at creating a little library, and did a poor job in doing so. – adeneo Oct 17 '16 at 22:56
  • @Bergi - I do like the functionality. I like to chain methods like jQuery. This functionality will be injected into a controller. I will read that link you posted. I would love some critique ;-) ..here is the source : https://www.youtube.com/watch?v=ABSperKuIYY – Daniel Oct 18 '16 at 00:05
  • @adeneo - That's correct .. It is meant for a little framework. – Daniel Oct 18 '16 at 00:06
  • @Daniel Is it just me or is that a video without sound? No commentary, just typing? There are so many so much better ones to watch. Btw, you forgot the invocation of the IIFE shown in the video. Regarding the question, just use `var q = {}` and drop the functions. About the rest of the code, I rather not comment, but if you want you can ask a question at [codereview.SE]. – Bergi Oct 18 '16 at 00:51
  • 1
    @Bergi - Yes, it is without sound. I adapted the code and added (a working) example to the above question. I read your post on constructor leakage. That was helpful. As for the rest I adapted the code a bit. I am sure I am in for critique and am a thankful receiver. I will have a look at Code Review and take my "beating" .. ;-) .. Thanks for the help here so far. – Daniel Oct 18 '16 at 01:01
  • @Bergi - You refer to better sources. Could you point out one or two that you know and carry better syntax? – Daniel Oct 18 '16 at 02:13
  • @Daniel Nah, I don't know any (I don't watch such), it's just when someone links a video and I skim over it they are of better quality usually. Maybe go by view count? – Bergi Oct 18 '16 at 11:08

3 Answers3

20

In the first case, you create a new object and you apply the Function constructor.

Return value is a function.

In the second example, you create a new object and you apply an anonymous function as constructor.

Return value is an object.

kube
  • 13,176
  • 9
  • 34
  • 38
  • …but not an ordinary object like you'd get from evaluating `{}` or `new Object`. – Bergi Oct 17 '16 at 22:50
  • Of course, because its `constructor` will point to the anonymous function passed after `new` operator, and its prototype chain will contain two prototypes, but it won't contain any other method than with an object created with `{}` or `new Object`. – kube Oct 17 '16 at 22:57
  • Thanks. Now I started to get the constructor through the comment. I do understand the constructor, but never really placed it into its context with the `function`. – Daniel Oct 18 '16 at 15:43
10

Both statements are indeed different. I will focus on the second statement to point out the difference.

var newObj1 = new function () {
    this.prop1 = "test1";
    this.prop2 = "test2"
};

Is equivalent to the following:

var Example = function () {
    this.prop1 = "test1";
    this.prop2 = "test2"
};

var newObj2 = new Example();

The only difference being that in the first example the constructor function called is an anonymous function. Note, that when a function is called with the new keyword in javascript it exhibits special behavior.

In your first statement the constructor function called is an already defined function, Function.

As has been pointed out your first statement returns a function while the second returns an object. Neither, is wrong but one returning a function and the other an object could have implications in other sections of your code.

Jorge Cabot
  • 181
  • 2
  • 10
  • The second function is "anonymous" too. ;-) – RobG Oct 18 '16 at 00:10
  • @RobG That's true... I guess I meant that the anonymous function was called immediately, instead of assigned and reused later on. – Jorge Cabot Oct 18 '16 at 00:16
  • It seems that [Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function#Difference_between_Function_constructor_and_function_declaration) should also be used in a different context, which is to take a string. Wouldn't the source code I posted be wrong at that? – Daniel Oct 18 '16 at 15:51
  • In the context of your code using an [object literal](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Grammar_and_types#Object_literals), like you did in your edit, is the better approach. What `Function` allows you to do is compose a function with strings (strings for arguments and for function body) but they lack closures so they can exhibit unexpected behavior. – Jorge Cabot Oct 20 '16 at 19:55
  • @RobG In the second example, the function is not anonymous as it's directly assigned to `Example`: Its `name` property equals `"Example"`. – kube Sep 29 '18 at 13:46
  • @kube—that is an inferred name which I think stems from ECMAScript 2015. The function is unreachable from inside itself (e.g. for recursion) because it doesn't have a name. Consider `var x = (function(){return function(){}}())`. Which function is/isn't anonymous? ;-) – RobG Sep 29 '18 at 13:57
2

Yes it is not right approach to create objects because objects created through new Function() are less efficient than the functions created using function expression

The global Function object has no methods or properties of its own, however, since it is a function itself it does inherit some methods and properties through the prototype chain from Function.prototype

for more reference https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function

Hope this helps

Check the following code snippet

var func = new Function();
func.property = "some property";
"some property"
console.log(func);

now when you check in the console it says it as anonymous but when an object created through function expression

var func=new function(){this.x=10;}
console.log(func);
this returns an objects I guess you understand the difference
Geeky
  • 7,420
  • 2
  • 24
  • 50
  • I don't think this at all answers the question – chiliNUT Oct 17 '16 at 22:40
  • 1
    "objects created through new Function() are less efficient than the functions created using function expression" --- this needs some scientific evidence. – zerkms Oct 17 '16 at 22:40
  • @zerkms regardless I don't think this is related to the question? – chiliNUT Oct 17 '16 at 22:41
  • @chiliNUT well, whether it addresses the initial question or not - is another story. My point was about that very phrase in isolation. – zerkms Oct 17 '16 at 22:42
  • @zerkms word. in isolation we are in agreement about that. – chiliNUT Oct 17 '16 at 22:45
  • They are less efficient because object created through Function would return anonymous function where as with expression it returns an object – Geeky Oct 17 '16 at 22:45
  • 2
    "They are less efficient because object created through Function would return anonymous function where as with expression it returns an object" --- this makes no sense, sorry. – zerkms Oct 17 '16 at 22:47
  • 2
    It's less efficient because the constructor takes a string as the function body, and that string would have to be parsed into code, doing some sort of evaluation. – adeneo Oct 17 '16 at 22:50
  • @Geeky—whether the function has a name or not is irrelevant, it's just a pointer to the function object. Performance tests across implementations have frequently shown that something that is more efficient in one is not in another, so broad claims about performance or efficiency must be supported by solid evidence from a broad spectrum of implementations. – RobG Oct 17 '16 at 22:51