На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Модераторы: ElcnU, ANDLL, fatalist
Страницы: (2) [1] 2  все  ( Перейти к последнему сообщению )  
> Function.prototype.bind
    Друзья приветствую вас, есть вопрос: чем отличается Function.prototype.bind от Function.prototype.call или apply?
    немного покодив пришел к выводу, что bind не просто возвращает функцию, которая вызывает другую функцию в нужном контексте, например:
    ExpandedWrap disabled
      var Person = {
          getName: function(){
              return this.name;
          }
      };
       
      var createPerson = function(specs){
          return {
              getName1: function(){
                  return Person.getName.call(specs);
              },
              getName2: Person.getName.bind(specs)
          };
      };
       
      var gregory = createPerson({name: 'Gregory'});
      console.log(gregory.getName1()); // Gregory
      console.log(gregory.getName2()); // Gregory

    на первый взгляд результат одинаковый, но вот в плане расхода памяти вызов call жрет больше чем bind, вы спросите как я понял это? да все просто я провел тесты! :D

    в связи с этим у меня возник этот вопрос, что там такого в bind, почему он расходует меньше памяти? :-?
    Сообщение отредактировано: Cfon -
      это я к тому что есть ли профит от Function.prototype.call, если bind выполнит тоже без проблем и судя по тестам еще и меньше памяти сожрет?
      ну я имею ввиду заменить вызов
      ExpandedWrap disabled
        Person.getName.call(specs);

      на
      ExpandedWrap disabled
        Person.getName.bind(specs)();
      Сообщение отредактировано: Cfon -
        :yes: ждём "гениальных" идей.
          Цитата K313 @
          :yes: ждём "гениальных" идей.

          гениальная идея уже озвучена! юзать bind вместо call :D
          остается понять в чем секрет bind, мои изучения вкладки Memory в консоли гугл хром показали, что при bind размер разделов closure и system/context меньше чем при вызове call.

          пс. надо потестить Function.prototype.apply чето про него забыл, где то читал, что вроде Function.prototype.call является оберткой apply :)

          Добавлено
          потестил c Function.prototype.apply результат почти одинаковый, возможно чуть меньше по отношению с Function.prototype.call.
          Сообщение отредактировано: Cfon -
            у bind и call разные предназначения, как я понял.... и разные производимые действия. Ты опять всё в одну кучу перемешал :whistle:
              Цитата K313 @
              у bind и call разные предназначения, как я понял.... и разные производимые действия. Ты опять всё в одну кучу перемешал :whistle:

              насколько разные?
              я понимаю что bind юзается там где требуется предавать функцию в нужном контексте, или юзать для частичного применения,
              а call и apply - вызов функции в нужном контексте.
              но потом то функцию, которую возвращает bind можно вызвать, что я и делаю.

              проверил тесты производительности на jsPerf.com и получил недвусмысленые результаты:
              [attach=#0][/attach]

              производительность bind выше чем call и apply, а расход памяти как я уже писал выше у bind меньше!
              Вывод? :D

              хотя это может тока на моем компе так :D, по идее bind должен быть и медленее и занимать больше памяти :)
              я смотрел пример кастомной реализации bind для ES3 (поскольку ее там нет) и она юзает замыкания, что должно сказаться на расходе памяти, а вот как она реализована в стандарте ES5 (Google Chrome 61 V8) я хз, но результаты тестов говорят за себя.
              можешь сам потестить jsPerf.com :)

              Кстати надо проверить кастомную версию bind.

              Добавлено
              протестил с кастомной версией bind и результаты подтвердились расход памяти значительно превысил то отношению к call и apply, думаю что скорее всего хром жаваскрипт движок V8 как то оптимизирует bind :)
              Сообщение отредактировано: Cfon -

              Прикреплённый файлПрикреплённый файлjsperf.jpg (72,25 Кбайт, скачиваний: 531)
                у тебя getName1 и getName2 - это кажись одно и тоже, просто первый это кастомный, а второй встроенный приёмы.
                  Цитата K313 @
                  у тебя getName1 и getName2 - это кажись одно и тоже, просто первый это кастомный, а второй встроенный приёмы.

                  ну да так и есть, я что об этом спрашивал? :wacko:
                  call это вызов функции в контексте, а bind - связывание функции с контекстом.
                  я пытаюсь тебе донести, что через bind памяти жрет меньше :D

                  Цитата Cfon @
                  хотя это может тока на моем компе так :D, по идее bind должен быть и медленее и занимать больше памяти :)
                  Сообщение отредактировано: Cfon -
                    а, ну да, просто я уже запутался в твоих схемах :wacko:

                    короче я тут выпендриваюсь потому что ты хочешь
                    Цитата Cfon @
                    это я к тому что есть ли профит от Function.prototype.call, если bind выполнит тоже без проблем и судя по тестам еще и меньше памяти сожрет?
                    ну я имею ввиду заменить вызов

                    а я пытаюсь тебе показать, что это разные вещи
                    ExpandedWrap disabled
                      function f( ) {
                          return this.user;
                      }
                       
                      f.user = "I'm result!"
                              
                       
                      alert( f( ) );
                      alert( f.call( { user: 'call Cfon' } ) );
                      alert( f.call( f ) );
                      alert( f.bind( { user: 'bind Cfon' } ) );
                      alert( f.bind( { user: 'bind after call Cfon' } )( ) );

                    что потом после твоиз замен, что-то может работать не так как ты ожидал :oops: кажися так.

                    Добавлено
                    а на счёт памяти, посмотри в своих тестах, при .bind( ... ) сохраняется в памяти текущий [[scope]] от вызова createPerson или нет? Если нет - вот тебе и экономия рамяти :whistle:

                    Добавлено
                    Цитата Cfon @
                    но потом то функцию, которую возвращает bind можно вызвать, что я и делаю.

                    а это я пропустил,... ты это оказываеся и без меня знаешь :rolleyes:
                      Цитата K313 @
                      а я пытаюсь тебе показать, что это разные вещи
                      ExpandedWrap disabled
                        function f( ) {
                            return this.user;
                        }
                         
                        f.user = "I'm result!"
                                
                         
                        alert( f( ) );
                        alert( f.call( { user: 'call Cfon' } ) );
                        alert( f.call( f ) );
                        alert( f.bind( { user: 'bind Cfon' } ) );
                        alert( f.bind( { user: 'bind after call Cfon' } )( ) );

                      что потом после твоиз замен, что-то может работать не так как ты ожидал :oops: кажися так.

                      Добавлено
                      Цитата Cfon @
                      но потом то функцию, которую возвращает bind можно вызвать, что я и делаю.

                      а это я пропустил,... ты это оказываеся и без меня знаешь :rolleyes:

                      обижаешь дружище! их назначение и применения я давно изучил :D
                      я же гений забыл? :blush:

                      Цитата K313 @

                      Добавлено
                      а на счёт памяти, посмотри в своих тестах, при .bind( ... ) сохраняется в памяти текущий [[scope]] от вызова createPerson или нет? Если нет - вот тебе и экономия рамяти :whistle:

                      вот я и спрашиваю у тех кто знает кухню движка JS например Google Chrome V8 что да как там с bind :)
                      сам я конечно смотрел на расход памяти по вкладке Memory консоли Google Chrome, но пока увидел то что писал выше в посте №1 :)

                      повторюсь меня интересует почему при bind расход памяти меньше чем при call или apply? :-?
                      козе понятно что у bind, call разное назначение, а мне гению тем более понятно :lool:
                      Сообщение отредактировано: Cfon -
                        Цитата Cfon @
                        обижаешь дружище! их назначение и применения я давно изучил
                        я же гений забыл?

                        я подумал, что пока ты о великом думал, какую-то мелочь упустил :D
                        Цитата Cfon @
                        почему при bind расход памяти меньше чем при call или apply?

                        может потому что при .call( ) у тебя замыкание, то есть текущий [[scope]] от createPerson нужно в памяти оставлять, а для .bind( ) не нужно??? ;)
                          Цитата K313 @
                          Цитата Cfon @
                          почему при bind расход памяти меньше чем при call или apply?

                          может потому что при .call( ) у тебя замыкание, то есть текущий [[scope]] от createPerson нужно в памяти оставлять, а для .bind( ) не нужно??? ;)

                          по идее bind
                          ExpandedWrap disabled
                            Person.getName.bind(specs);

                          это тоже что и
                          ExpandedWrap disabled
                            function(){
                              return Person.getName.call(specs);
                            }

                          вот пример кастомного бинда (полифила для ES3)
                          ExpandedWrap disabled
                            Function.prototype.custom_bind = function (thisArg) {
                                var fn = this,
                                    slice = Array.prototype.slice,
                                    args = slice.call(arguments, 1);
                                return function () {
                                    return fn.apply(thisArg, args.concat(slice.call(arguments)));
                                };
                            };

                          поэтому я не понял почему при bind расход памяти больше, хотя как я уже писал выше если заменить bind ES5 на этот custom_bind, то расход памяти сразу увеличивается, что говорит о том что скорее всего bind es5 как то оптимизируется :)
                          Сообщение отредактировано: Cfon -
                            Цитата Cfon @
                            при bind расход памяти больше

                            в смысле - меньше :)

                            Цитата Cfon @
                            это тоже что и

                            при .call он у тебя выполняется, когда ты вызываешь
                            ExpandedWrap disabled
                              console.log(gregory.getName1()); // Gregory


                            а .bind у тебя выполняется ещё при вызове
                            ExpandedWrap disabled
                              var gregory = createPerson({name: 'Gregory'});


                            чуешь разницу? ;)

                            поэтому я думаю что для .bind замыкание не нужно, в памяти достаточно сохранять только переданный .bind-у объект. :whistle:

                            Добавлено
                            прежняя аватарка была круче <_<
                              Цитата K313 @
                              Цитата Cfon @
                              при bind расход памяти больше
                              в смысле - меньше :)

                              опечатался, конечно же меньше :)
                              я запускал свои тесты в хроме и делал heap snapshot, потом сравнивал и размер при bind был 4.7Mb, при call - 5.5Mb.

                              Цитата K313 @
                              Цитата Cfon @
                              это тоже что и

                              при .call он у тебя выполняется, когда ты вызываешь
                              ExpandedWrap disabled
                                console.log(gregory.getName1()); // Gregory

                              а .bind у тебя выполняется ещё при вызове
                              ExpandedWrap disabled
                                var gregory = createPerson({name: 'Gregory'});

                              чуешь разницу? ;)
                              поэтому я думаю что для .bind замыкание не нужно, в памяти достаточно сохранять только переданный .bind-у объект. :whistle:

                              ок а почему тогда при кастомном бинде памяти жрет больше чем при call?
                              если следовать твоему предположению она не должна жрать больше памяти или я чего не понял? :)

                              Цитата K313 @
                              Добавлено
                              прежняя аватарка была круче <_<

                              :D :D
                              Сообщение отредактировано: Cfon -
                                Цитата Cfon @
                                ок а почему тогда при кастомном бинде памяти жрет больше чем при call?

                                наверно потому что кастомный .bind тоже на замыкании строится, да ещё похлеще твоего .call в createPerson :scratch:

                                Добавлено
                                а так, х его знает, это всё предположения <_<
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0929 ]   [ 18 queries used ]   [ Generated: 28.03.24, 23:22 GMT ]