【问题标题】:Most optimized way to create JS Object创建 JS 对象的最优化方式
【发布时间】:2012-01-31 06:40:57
【问题描述】:

我正在寻找在 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”不能被公共更改或读取,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 中的内容,不同之处在于我确保原型方法仅设置一次且仅在需要时设置。

所以最后的问题是,您会建议我遵循哪些方法,或者如果其中任何一种方法是最佳做法?

【问题讨论】:

  • 虽然没有公共 name 属性,但 getName 是公共的并且可以被替换,因此可以有效地修改 name .上述内容对公共 name 属性没有任何好处,它只是为闭包和额外的函数调用使用更多资源来访问该值。不过,使用 getter 是有正当理由的。

标签: javascript oop optimization constructor prototype


【解决方案1】:

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

/**
 * @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 好吧,没那么重要。但是还是……

【讨论】:

  • 您好,感谢您的回复! :) 只是一个问题,如果我们说我不在乎财产是否可以公开访问,那么您更喜欢哪种方式,为什么?可能是通过对性能问题的方法进行原型设计吧?
  • @panosru:可能是通过对方法进行原型设计。它可能性能更高,但重要的是您可以执行Person.prototype.getName.call(someObj) 之类的操作。
  • 在这两者之间,您更喜欢哪一个,为什么? #1 function Person (name) { this.getName = function () { return name; } } #2 function Person (name) { return { getName : function () { return name; } } }
  • @panosru:肯定是this.getNameHere's why.
  • 好点!非常感谢您和@qwertymk 的回复非常有帮助! :)
【解决方案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 引擎必须“向上”运行原型链时,它会占用几分之一毫秒(或 IE 上几分之一秒 :)),而声明变量可能会占用时间(也可以忽略不计)避免这样做。希望有帮助

【讨论】:

  • 对于示例 #3 是的,我同意你的观点,但为什么示例 #4?由于放置了一个标志,因此原型设计实际上不会被设置超过一次,并且仅在需要时设置。
  • @panosru: 因为检查 (if) 也会占用一些计算能力和时间。
  • 当然是的,但除此之外没有任何“问题”,我的意思是使用这种方式对吗?我实际上从未使用过它,我只是在这里看到它:stackoverflow.com/a/546717/395187 这就是我问的原因:)
【解决方案3】:

在 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());

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-10-14
    • 1970-01-01
    • 2017-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多