Javascript 类、编译器性能和新 Klass() 上的内存分配

Javascript classes, compiler performance and memory allocation on new Klass()

本文关键字:分配 内存 Klass 编译器 性能 Javascript      更新时间:2023-09-26
EDIT:
========================================================
Please see revision 13 of this test for answers: 
http://jsperf.com/closure-prototype-static-performance/
========================================================

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

第一种方式:私人范围界定

    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 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功率,为什么或何时应该尝试避免或遵循另一种方法?

阿拉伯数字。从这个角度来看,最后一个"静态"范围界定的例子是否比原型方法更好?

3.当涉及到第一种方式时,这是我更喜欢的方式,因为它更整洁,允许"私有"范围,并且所有代码都非常适合,编译器是否可能为您执行原型方法,或者是否为您所做的每个新人一遍又一遍地声明这些函数?

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

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?
            }
    }

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

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

有什么理由为什么或什么时候应该试图避免或遵循它吗?

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

最后一个"静态"范围示例是否比原型方法更好?

查找可能会便宜一点,但不在乎这个。将实例方法放在实例(或其原型(上更简洁,并避免了全局范围的污染。

编译器是否可能为您执行原型方法,或者是否为您执行的每个新人一遍又一遍地声明这些函数?

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

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

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

注意到我的示例不包含"私有"函数

是的,确实如此。employedequals 函数表达式与函数声明一样具有私有作用域。

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

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