-3
EDIT:
========================================================
Please see revision 13 of this test for answers: 
http://jsperf.com/closure-prototype-static-performance/
========================================================

我通常更喜欢这样声明我的类,因为我不是对象字面量方式的忠实粉丝:

第一种方式:私有范围

    function Employees() {
            var persons = []; // [Person, Person]

            this.isEmployed = function(_firstName, _lastName) {
                    for ( var i = 0; i < persons.length ; i++ ) {
                            if ( persons[i].equals(_firstName, _lastName) ) {
                                    return true;
                            }
                    }
                    return false;
            }
    }

    function Person(_firstName, _lastName) {
            this.equals = function(firstName, lastName) {
                    return _firstName == firstName && _lastName == lastName;
            }
    }

第二种方式:原型

另一种方法是使用原型,但是您将无法访问“私有”属性,例如 var people = [] 和 Person(...) 中的参数,但是人们可以忍受将它们公开,尽管对于 person将引入两个新属性:

    function Employees() {
            this.persons = []; // [Person, Person]
    }
    Employees.prototype.isEmployed = function(_firstName, _lastName) {
            for ( var i = 0; i < this.persons.length ; i++ ) {
                    if ( this.persons[i].equals(_firstName, _lastName) ) {
                            return true;
                    }
            }
            return false;
    };

    function Person(_firstName, _lastName) {
            this.firstName = _firstName;       // Two new properties. Are these or the function declared more expensive?
            this.lastName  = _lastName;
    }
    Person.prototype.equals = function(firstName, lastName) {
            return this.firstName == firstName && this.lastName == lastName;
    };

第三种方法:静态方法

另一种选择是像原型一样做,而是在“静态”之外创建方法:

    function Employees() {
            this.persons = []; // [Person, Person]
    }
    function isEmployed(employee, _firstName, _lastName) {
            for ( var i = 0; i < employee.persons.length ; i++ ) {
                    if ( equals(employee.persons[i], _firstName, _lastName) ) {
                            return true;
                    }
            }
            return false;
    }
    function Person(_firstName, _lastName) {
            this.firstName = _firstName;       // Two new properties. Are these or the function declared more expensive?
            this.lastName  = _lastName;
    }
    function equals(person, firstName, lastName) {
            return person.firstName == firstName && person.lastName == lastName;
    }

问题:

1. 您认为哪种方法最适合性能、内存和 CPU 功率,是否有任何理由说明为什么或何时应该尝试避免或遵循另一种?

2. 从这个角度来看,最后一个具有“静态”作用域的示例是否比原型方法更好?

3. 当谈到第一种方式时,这是我更喜欢的方式,因为它更整洁,允许“私有”范围,并且所有代码都很好地适合,编译器可能会为你做原型方法,或者是这些函数一遍又一遍地为每个新的 Person 声明你做什么?

当我执行 new() 并且涉及很多方法时,我尽量避免使用第一种方法,然后我通常会采用静态方法,尽管我想知道我是否有任何真正好的理由这样做?

4. 我注意到我的示例没有包含“私有”函数,那么编译器如何处理它们?

例子:

    function Person(_firstName, _lastName) {
            function privateFunction() {
                    // How does the compile treat private functions. Are they also created once per new Person() ? Cheap or expensive?
            }
    }
4

1 回答 1

2

您认为哪种方法最适合性能、内存和 CPU 功率?

请参阅Javascript 原型运算符性能:节省内存,但更快吗?通过原型定义方法与在构造函数中使用它 - 真的是性能差异吗?. 原型确实可以节省内存。

是否有任何理由说明为什么或何时应该尝试避免或遵循它?

只有当您真正关心隐私时,您才会使用特权方法和作用域变量。

最后一个具有“静态”作用域的示例是否比原型方法更好?

查找可能会便宜一些,但不要在意。将实例方法放在实例(或它们的原型)上更干净,并且避免了全局范围污染。

编译器可能会为您执行原型方法,还是为您所做的每个新 Person 一遍又一遍地声明这些函数?

当然,它是由解释器(或至少是现代的)优化的。可执行代码将被共享,但为了保持指定的语义,将创建具有不同范围指针的不同函数对象。

当我经常执行 new() 并且涉及很多方法时,我会尽量避免使用第一种方法,然后我通常会采用静态方法。

你当然可以将它们组合起来。可能并非所有方法都需要访问私有变量,然后您可以将它们放在原型上。

我注意到我的示例没有包含“私人”功能

是的,它确实。employedand函数表达式与equals函数声明一样是私有范围的。

它们是否也每次创建一次new Person()?便宜还是贵?

当然,它们是-针对每个不同的范围一次。没那么贵,但如果你能让它们成为静态的(将它们放在构造函数范围之外)它们会更便宜。

于 2013-07-17T13:21:17.593 回答