不使用“new”构建对象

时间:2011-07-31 10:11:49

标签: javascript

如何重写此对象,以便您不需要使用“new”声明它?

var Lang = new function(){
    this.get = function(str, trans){
        if(TRANSLATE[str]){
            var str = TRANSLATE[str][LANG];
            if(count_obj(trans) > 0){
                for(var key in trans){
                    str = str.replace('%'+key+'%', trans[key]);
                }
            }
        }

        return str;
    };
};

对于这样的事情:

var Lang = {
get : function(){}
};

3 个答案:

答案 0 :(得分:1)

您在问题中为自己的问题编写了解决方案...这是在javascript中创建对象的完全有效的方法:

var Lang = {
    get: function(str, trans){
        if(TRANSLATE[str]){
            var str = TRANSLATE[str][LANG];
            if(count_obj(trans) > 0){
                for(var key in trans){
                    str = str.replace('%'+key+'%', trans[key]);
                }
            }
        }

        return str;
    };
};

如果你想要私有变量,通常的做法是创建一个带有局部变量的函数,这些函数返回对象,并将这些变量封装在一个闭包中,如下所示:

var Lang = (function() {
    var p1; // private variable
    var p2; // another private variable

    return {
       getP1: function () {
          return p1;
       },
       setP1: function(value) {
          p1 = value;
       }
    };
})();

请注意,创建所需对象的函数会立即执行,并返回带有在闭包中捕获的两个私有变量的对象。这些变量将无法从对象外部访问。

答案 1 :(得分:1)

实施新的模式

如上所述,构造函数仍然只是函数,但是使用new调用。 什么 如果你在调用构造函数时忘记了new,会发生什么?这不会导致 语法或运行时错误,但可能导致逻辑错误和意外行为。 那是因为当你忘记new时,构造函数内部将指向全局 宾语。 (在浏览器中,这将指向窗口。)

当你的构造函数有类似this.member的东西时,你调用构造函数 没有new,你实际上是在创建一个名为的全局对象的新属性 成员,可通过window.member或简单的成员访问。这种行为非常重要 不可取的,因为你知道你应该总是努力保持全局命名空间 干净。

// constructor
function Waffle() {
   this.tastes = "yummy";
}
// a new object
var good_morning = new Waffle();
console.log(typeof good_morning); // "object"
console.log(good_morning.tastes); // "yummy"
// antipattern:
// forgotten `new`
var good_morning = Waffle();
console.log(typeof good_morning); // "undefined"
console.log(window.tastes); // "yummy"

自我调用构造函数

解决先前模式的缺点并提供原型属性 对于实例对象,请考虑以下方法。在你的构造函数中 检查这是否是构造函数的实例,如果不是,则构造函数调用 再次,这次适当的新:

function Waffle() {
   if (!(this instanceof Waffle)) {
      return new Waffle();
   }
   this.tastes = "yummy";
}
Waffle.prototype.wantAnother = true;
// testing invocations
var first = new Waffle(),
second = Waffle();
console.log(first.tastes); // "yummy"
console.log(second.tastes); // "yummy"
console.log(first.wantAnother); // true
console.log(second.wantAnother); // true

另一种检查实例的通用方法是与之比较 arguments.callee而不是硬编码构造函数名称。

if (!(this instanceof arguments.callee)) {
   return new arguments.callee();
}

此模式使用这样的事实:在每个函数内部,创建一个名为arguments的对象 包含调用时传递给函数的所有参数。和争论 有一个名为callee的属性,它指向被调用的函数。是 意识到在ES5的严格模式下不允许使用arguments.callee,所以最好是限制 它的未来使用,如果您在现有代码中找到它们,也会删除任何实例。

“JavaScript模式,Stoyan Stefanov(O'Reilly)。版权所有2010 Yahoo!,Inc.,9780596806750。“

答案 2 :(得分:0)

只剩下“新”出来,休息是一样的。 :)

var Lang = function(){ 
...
}

编辑:来自firebug的示例复制粘贴,“dsa”只是一个对象,“dsaFunc”是一个函数,但你可以对它们做同样的事情:

>>> var dsa = {};
undefined
>>> dsa.get = function(a){ return a+1;}
function()
>>> dsa.get(2)
3
>>> var dsaFunc = function(){};
undefined
>>> dsaFunc.get = function(a){ return a+1;}
function()
>>> dsaFunc.get(2)
3