Символы, как ключ объекта в Spidermonkey - PullRequest
0 голосов
/ 18 апреля 2020

Прошлой ночью я прочитал статью на mdn о символах и обнаружил, что это здорово. Я всегда использовал какие-то псевдоклассы в Javascript с конструктором и прототипом и думал об использовании символов в качестве некоторого хранилища для частных объектов, свойств, методов, но после экспериментов и тестирования кажется, что spidermonkey очень медленно работает с символами как ключ объекта или я сделал что-то не так, но у меня нет этой проблемы с хромом.

Можете ли вы сказать мне, есть ли способ сделать более быстрый доступ к объектам по символам?

Допустим, я иметь псевдо-класс с конструктором и прототипом с именем test

//********************************************************
//-------------------------------------- Class test normal
//********************************************************

{//----------------------------------- BlockScope

//-----------------------------------------------------
//-------- constructor
//----------------------------------------------------- 
    let CONSTR=EFTA.Classes.test=function (x,y) //-- Short Reference CONSTR
        {

        var private_x=20, private_y=30, private_z=50, that=this;

        function private_method () // has access to PRIVATE properties, methods
            {
            PROTO.public_calculation_counter++;     
            return that.public_x+that.public_y+private_x+private_y; 
            }

        this.public_x=x;
        this.public_y=y;

        this.public_methodA=function () {return private_method ()+private_z;}  //-- has access to PRIVATE properties, methods
        }
//-----------------------------------------------------
//-------- constructor -- END
//-----------------------------------------------------

//-----------------------------------------------------
//-------- prototype
//-----------------------------------------------------

  //-- Set Short Reference
    let PROTO = CONSTR.prototype;  //-- Short Reference to prototype

    PROTO.public_calculation_counter=0;     //-- property only linked on each instance

    //-- normal public prototype method - has no access to PRIVATE properties
    PROTO.public_methodB=function ()
        {
        return this.public_x*this.public_y;
        }

//-----------------------------------------------------
//-------- prototype - END
//-----------------------------------------------------

} //-------------------------------- BlockScope -- END

//********************************************************
//-------------------------------------- Class test normal -- END
//********************************************************

public_methodB - это обычный метод прототипа, не имеющий доступа к объекту PRIVATE, методы и свойства public_methodA определены внутри конструктора, поэтому он имеет доступ к объекту PRIVATE, методы и свойства.

каждый раз, когда конструктор запускается, он генерирует новую функцию (private_method) и новую функцию (public_methodA), public_methodB связан только в прототипе

Теперь я хотел реорганизовать этот сценарий , так что public_methodA и private_method создаются только один раз и для всех экземпляров одинаково.

, поэтому я генерирую Symbol

EFTA.Classes.Symbols.priv=Symbol ();

этот ключ уникального идентификатора, который я сейчас использую для хранения private_ ( x | y | z) в экземпляре, подобном папке

const EFTA={};
EFTA.Classes={};
EFTA.Symbols=
    {
    dom :Symbol (),       //-- storage key on dom elements
    priv:Symbol ()        //-- storage key for private object, methods and properties
    };

//**************************************************************
//-------------------------------------- Class test with Symbols
//**************************************************************

{//----------------------------------- BlockScope

//-----------------------------------------------------
//-------- constructor
//----------------------------------------------------- 
    let CONSTR=EFTA.Classes.test_with_Symbols=function (x,y) //-- Short Reference CONSTR
        {       
        this.public_x=x;
        this.public_y=y;

        //-- instance folder for PRIVATE objects and properties existing on each instance - hided by Symbol
        this[priv]=
            {
            private_x:20,
            private_y:30,
            private_z:50
            }
        }
//-----------------------------------------------------
//-------- constructor -- END
//-----------------------------------------------------

  //-- Set Short References
    let PROTO = CONSTR.prototype,            //-- Short Reference to prototype
        priv  = EFTA.Symbols.priv;           //-- Short Reference to Symbol (unique identifier)

, и теперь я установил public_methodA для прототипа, который был первым в конструкторе. теперь он может получить доступ к свойствам PRIVATE этим [priv], он связан только с экземпляром


//-----------------------------------------------------
//-------- prototype
//-----------------------------------------------------

    PROTO.public_calculation_counter=0;     //-- property only linked on each instance

    PROTO.public_methodA=function ()        //-- method only linked on each instance
        {
        return privFolder.private_method.call (this)+this[priv].private_z;   //-- call a PRIVATE method from a public method (prototype)
        } 

    //-- normal public prototype method - has now also access to PRIVATE properties, methods over privFolder. (constructor Folder) or this[priv] (instance folder)
    PROTO.public_methodB=function ()
        {
        return this.public_x*this.public_y;
        }

//-----------------------------------------------------
//-------- prototype - END
//-----------------------------------------------------

, теперь я установил в конструкторе вторую папку с этим ключом уникального идентификатора, куда я поместил все методы PRIVATE здесь только один -> private_method

  //-- constructor Folder for PRIVATE objects, methods and properties stored in the constructor (test) - hided by Symbol
    CONSTR[priv]=
        {
        private_method: function ()     //--- private method not stored on each instance
            {
            PROTO.public_calculation_counter++;
            return this.public_x+this.public_y+this[priv].private_x+this[priv].private_y;
            },

        private_test:"Hello World"     //--- private property not stored on each instance - Additional
        }

    let privFolder=CONSTR[priv];  //-- Short Reference to the Folder on the constructor

этот private_method можно вызвать с privFolder.private_method.call (this), чем он имеет доступ к свойствам экземпляра publi c, а также к свойствам PRIVATE с помощью этого [priv ] каждого экземпляра.

я провел тест на https://jsfiddle.net/ThorstenArtnerAustria/7osf8kc9/15/

создал экземпляры с нормальным классом test Firefox: 876ms создал экземпляры с тестом класса с символами. Это быстрее, чем в два раза меньше Firefox: 376 мс

, чем то, что я выполнил public_methodA с тестом класса Firefox: 70 мс и public_methodA с тестом класса Символы Firefox: 523 мс

в chrome я получаю за создание 605 мс | 213 мс и для выполнения 85 мс / 115 мс

, если я изменяю в Firefox все это [priv] на этот ["priv"] с Symbol на обычный строковый идентификатор, я получаю 68ms, который был первым 523ms

Кажется, что доступ к символу очень медленный на объекте, или я что-то не так?

...