最优化的方法来创建JS Object

时间:2012-01-01 03:29:43

标签: javascript oop optimization constructor prototype

我正在寻找在JS中拥有对象的最优化方法;因为JS允许你以多种方式做某事我想知道哪些被认为是“最佳实践”。

对象的概念用法是:

var John = new Person('John');
var Foo = new Person('Foo');

console.log(John.getName()); //Return 'John'
console.log(Foo.getName()); //Return 'Foo'
console.log(John.name); //undefined
console.log(Foo.name); //undefined

我在这里有一些例子:

示例#1:

var Person = function (name) {
    this.getName = function () { return name; }
}

这里我实际上没有属性; “name”无法更改或由public读取,getName方法可以公开访问,并使用本地名称变量调用。这实际上满足了我的需求。

示例#2:

function Person (name) {
    this.getName = function () { return name; }
}

这与示例#1具有相同的行为。从功能和性能的角度来看,我只是不确定var method = function () {};function method() {};之间的区别。

示例#3:

var Person = function (name) {
    this.name = name;    
    Person.prototype.getName = function () { return this.name; }
}

这里我有name属性,可以公开读/写,我也有一个可以公开访问的原型getName方法。

示例#4:

var Person = function (name) {
    this.name = name;
    if (!Person._prototyped) {
        Person.prototype.getName = function () { return this.name; }
        Person._prototyped = true;
    }
}

这里我有我在示例#3中所拥有的,区别在于我确保原型方法只设置一次且仅在需要时。

所以最后一个问题是,你建议我遵循哪些或者其中哪一个是最佳做法?

3 个答案:

答案 0 :(得分:3)

对于你想要的,最好的方法可能就是:

/**
 * @constructor
 */
function Person(name) {
    this.getName = function() {
        return name;
    };
}

这是为什么?好吧,首先,封装。如果可能,您通常希望将函数放在原型中,如下所示:

/**
 * @constructor
 */
function Person(name) {
    this.name = name;
}

Person.prototype.getName = function() {
    return this.name;
};

但是!在这种情况下,您似乎不希望Person.name可访问。因此,您需要使用闭包。

至于这种方法:

var Person = function (name) {
    this.name = name;    
    Person.prototype.getName = function () { return this.name; }
}

那不好。您公开公开this.name,因此它没有优先于以前的原型方法,但您不断使用相同的函数覆盖Person.prototype.getName。这样做是没有意义的; this每次都是适当的对象。更重要的是,在第一个Person.prototype.getName对象被实例化之前,Person将无法访问,因此首先将其设置为“公共”没有太大意义。你的第四个例子基本相同,更难以理解,但它仍然具有所有的缺点。

所以,在这种情况下,请使用第一个版本;但是,尽可能在prototype上设置方法,以便可以在实例外部调用它们。

最后,我建议使用:

function Person() {
}

var Person = function() {
}

因为1)第二个例子缺少一个分号,2)var暗示构造函数是变量,它不应该是,3)我不相信JDoc允许@constructor应用于它,导致Closure Compiler中的警告至少 1


1 好的,不是那么重要。但仍然......

答案 1 :(得分:2)

在示例3和4中,它应该是:

var Person = function (name) {
    this.name = name;    
};
Person.prototype.getName = function () { return this.name; }

var Person = function (name) {
    this.name = name;
};

if (!Person._prototyped) {
    Person.prototype.getName = function () { return this.name; }
    Person._prototyped = true;
}

因为每次调用构造函数时都不需要弄乱原型。

不确定哪个最快(因为它们都适用于您的目的),这是您的要求,但我不担心,因为这似乎是微优化。如果您必须知道,那么您可以使用http://jsperf.com/

这样的网站

我能想象的最快方式是:

function Person(name) {
    this.getName = function() {
        return name;
    };
}

正如minitech所说。原因如下:

每次js引擎必须“向上”原型链时,它会消耗掉一小部分ms(或IE上的一小部分:)),并且因为声明变量会占用时间(也可以忽略不计)避免这样做。希望有所帮助

答案 2 :(得分:0)

在node.js上运行良好。 AFAIK,论证是可变的。闭包会记住价值观。因此,这将有效。我想这解决了这一切。

var Person = function(Name) {
    this.getName = function(){return Name;}
    this.setName = function(newName)  { Name = newName; }
},

me  = new Person('John');
console.log(me.getName());
me.setName('Peter');
console.log(me.getName());