new function(){}与new Function();的区别

20

我拾取了一些代码,现在才开始理解new Function();。通过jslint检查时,new Function();被标记为意外的。我开始进行以下实验。

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

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

两者都可以工作,但第二种方法被js-lint忽略。

我是否在这里做了什么特别的事情,还是完全相同?像这样使用new Function();在语法上是否正确?

附上原始代码摘录。

 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;


   });
 })

这两个代码语法有误吗?

编辑 在获得一些很好的建议后,我将代码改为以下形式:

请注意,以上内容保留了HTML标签。

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>

它工作得非常好,看起来更加清晰。JS Lint对我很友好,我可以解决下一个问题。


2
你的代码中为什么要使用 Function 而不是对象 {} - zerkms
1
当然,在语法上是正确的,否则在加载文件时会出现语法错误。JSLint标记它是因为Crockford认为你不应该创建那样的函数。另外,我同意@zerkms的观点;他们两个都没有做任何你不能用var q = {};来实现的事情。 - Heretic Monkey
2
它们做了不同的事情。typeof (new Function) === "function"typeof (new function(){}) === "object" - chiliNUT
3
永远不要使用 new function - Bergi
2
这两种语法都有很多问题。你实际上想做什么?你需要什么结果?func应该是一个函数吗?如果是,当调用时它应该做什么?是的,你真的可能需要在你的原始代码上进行[CodeReview.SE](至少从你展示的摘录来看)。 - Bergi
显示剩余13条评论
3个回答

20
在第一个例子中,您创建了一个新对象并应用 Function 构造函数。

返回值是一个函数

在第二个例子中,您创建了一个新对象并将匿名函数作为构造函数应用。

返回值是一个对象


但它不是像 {}new Object 这样的普通对象。 - Bergi
当然,因为它的constructor将指向在new操作符后传递的匿名函数,并且它的原型链将包含两个原型,但它不会包含任何其他方法,除了使用{}new Object创建的对象。 - kube
谢谢。现在我开始通过注释理解构造函数了。我确实理解构造函数,但从未真正将其放入与“function”相关的上下文中。 - Daniel

10

这两个声明确实不同。我将重点关注第二条声明,以指出它们之间的差异。

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

等价于以下内容:

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

var newObj2 = new Example();
唯一的区别是在第一个例子中调用的构造函数是匿名函数。请注意,当使用 JavaScript 中的 new 关键字调用函数时,它会表现出特殊行为
在您的第一种语句中,调用的构造函数是一个已定义的函数Function
正如已经指出的那样,您的第一种语句返回一个函数,而第二种语句返回一个对象。两者都不是错的,但返回函数和返回对象可能会影响您代码的其他部分。

第二个函数也是“匿名”的。;-) - RobG
@RobG 这是真的... 我想我是指匿名函数立即被调用,而不是分配并在以后重复使用。 - Jorge Cabot
看起来Function也应该在不同的上下文中使用,即接受一个字符串。我发布的源代码难道不是错误的吗? - Daniel
在您的代码中使用对象字面量是更好的方法,就像您在编辑中所做的那样。Function允许您将函数与字符串(用于参数和函数体的字符串)组合在一起,但它们缺乏闭包,因此可能会出现意外行为。 - Jorge Cabot
@RobG 在第二个例子中,该函数不是匿名的,因为它直接分配给了 Example:它的 name 属性等于 "Example" - kube
@kube——这是一个我认为源自ECMAScript 2015的推断名称。该函数无法从内部访问(例如递归),因为它没有名称。考虑var x = (function(){return function(){}}())。哪个函数是/不是匿名的?;-) - RobG

2
是的,创建对象的方法不正确,因为通过new Function()创建的对象比使用函数表达式创建的函数效率低。
全局Function对象本身没有自己的方法或属性,但由于它本身是一个函数,所以它通过原型链从Function.prototype继承了一些方法和属性。
更多信息请参考:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function
希望这可以帮助你。
请查看以下代码片段。

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

现在当您在控制台中检查时,它会显示为匿名,但是当通过函数表达式创建对象时

var func=new function(){this.x=10;}
console.log(func);

this returns an objects I guess you understand the difference


我认为这完全没有回答问题。 - chiliNUT
1
通过 new Function() 创建的对象比使用函数表达式创建的函数效率低,这需要一些科学证据。 - zerkms
@zerkms 不管怎样,我认为这与问题无关? - chiliNUT
2
很抱歉,这句话没有意义。 - zerkms
2
它的效率较低,因为构造函数将字符串作为函数体,该字符串必须被解析成代码,进行某种形式的评估。 - adeneo
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接