`新函数()`with lower case";f";在JavaScript中

`新函数()`with lower case";f";在JavaScript中,javascript,function,object,instantiation,Javascript,Function,Object,Instantiation,我的同事一直在使用带有小写字母“f”的“new function()”来定义JavaScript中的新对象。它似乎在所有主流浏览器中都能很好地工作,而且似乎在隐藏私有变量方面也相当有效。下面是一个例子: var someObj = new function () { var inner = 'some value'; this.foo = 'blah'; this.get_inner = function () {

我的同事一直在使用带有小写字母“f”的“new function()”来定义JavaScript中的新对象。它似乎在所有主流浏览器中都能很好地工作,而且似乎在隐藏私有变量方面也相当有效。下面是一个例子:

    var someObj = new function () {
        var inner = 'some value';
        this.foo = 'blah';

        this.get_inner = function () {
            return inner;
        };

        this.set_inner = function (s) {
            inner = s;
        };
    };
一旦“this”被使用,它就成为someObj的公共财产。所以someObj.foo、someObj.get_inner()和someObj.set_inner()都是公开的。此外,set_inner()和get_inner()是特权方法,因此它们可以通过闭包访问“inner”

然而,我还没有看到任何地方提到过这种技术。就连道格拉斯·克罗克福德的JSLint也对此表示不满:

  • 奇怪的构造。删除“新建”

我们正在生产中使用这种技术,它似乎工作得很好,但我有点担心它,因为它在任何地方都没有记录。有人知道这是一种有效的技术吗?

我以前见过这种技术,它是有效的,您使用的函数表达式就像它是一个函数表达式一样

但是,IMHO,您可以通过自动调用函数表达式实现同样的效果,我真的不认为以这种方式使用
new
操作符有什么意义:

var someObj = (function () {
    var instance = {},
        inner = 'some value';

    instance.foo = 'blah';

    instance.get_inner = function () {
        return inner;
    };

    instance.set_inner = function (s) {
        inner = s;
    };

    return instance;
})();
new
操作符的目的是创建新的对象实例,设置
[[Prototype]]
内部属性,您可以看到内部属性是如何实现的


上面的代码将产生一个等价的结果。

您的代码与不太奇怪的构造类似

function Foo () {
    var inner = 'some value';
    this.foo = 'blah';

    ...
};
var someObj = new Foo;

为了澄清某些方面并使Douglas Crockford的JSLint不抱怨您的代码,以下是一些实例化示例:

1。o=新对象();//构造函数的正常调用
2.o=新对象;//构造函数的已接受调用
3.var someObj=new(函数(){
var-internal='某些值';
this.foo='blah';
this.get_inner=函数(){
返回内部;
};
this.set_inner=函数{
内=s;
};
})(); // 构造函数的正常调用
4.var someObj=new(函数(){
var-internal='某些值';
this.foo='blah';
this.get_inner=函数(){
返回内部;
};
this.set_inner=函数{
内=s;
};
}); // 构造函数的已接受调用
在例3中。(…)中的表达式作为值是函数/构造函数。看起来是这样的: 新的(函数(){…})()。因此,如果我们像示例2中那样省略了结束括号,那么表达式仍然是一个有效的构造函数调用,看起来像示例4


Douglas Crockford的JSLint“认为”您想要将函数分配给someObj,而不是它的实例。毕竟,这只是一个警告,而不是一个错误。

第13节中的ECMAScript 262规范更正式地解释了这一点。类似于
function foo(){}
的内容返回创建
函数的结果[可能是使用新函数()]。我认为您缺少了一个
return实例在末尾。否则,
someObj
将只是
未定义如果您关心模块化和信息隐藏,我可以建议您放弃这一点,开始使用require.js之类的东西吗?你已经走到一半了,为什么停在这里?异步模块定义(这是require.js实现的)支持此用例,并为您提供了处理范围界定的完整工具集,名称空间和依赖关系管理。请注意,函数声明周围的括号是不必要的,因为由于存在
=
@StijndeWitt,语句已经是一个表达式,这意味着您需要做两倍的工作才能使用require.js,但在简单的情况下,这可能就是您所需要的。这不仅仅是类似的,它做的事情完全一样。。。唯一的例外是,他们不能重用Foo来创建另一个对象。OP的版本可以通过新的someObj.constructor重用。这里构造函数被显式地添加到名称空间中;正确的样式取决于功能的预期用途。此外,这种样式(当然是标准样式)允许某些人在忘记Foo之前的new时填充全局名称空间。@kikito这不允许重用Foo来创建另一个对象是什么意思?var newObj=new Foo()应该创建一个新实例。@BillYang,那是5年前的事了。不知道。从那以后我再也没有接触过javascript。我更喜欢你的构造而不是IIFE(“立即调用的函数”)。1:您不需要显式的“instance”对象,这正是JavaScript中的“this”所在。2:你不需要归还任何东西,也就是说,你不需要记得归还。即使是接受答案的作者最初也忘了返回实例对象!如果人们不喜欢新的,通常更喜欢使用iLife&这是有充分理由的-如果你有一个处理DOM事件的函数,
this
将引用触发事件的元素,而不是你的对象,但是你可以只使用
var instance=this
。为什么指定“小写f”对问题很重要?因为在Javascript中也存在“Function”函数(大写F),这是不同的:Function是一个可以创建新函数对象的构造函数,而Function是一个关键字。相关:关于为什么使用这个模式@Bergi,我阅读了您的链接。我认为没有理由怀疑这种模式。这是有效的。很简单。那怎么了。JSLint抱怨一切(顺便说一句:)