Накарайте Closure Compiler да обедини няколко декларации за свойства на обекти в един голям литерал

Разделих кода си на няколко файла и след това стартирах скрипт, за да ги обединя и компилирам (с ADVANCED_OPTIMIZATIONS). Голяма част от функционалността е реализирана в прототип на един обект.

Така че, когато се слее, може да изглежда така:

(function(){

/** @constructor */ function MyConstructor() {};

MyConstructor.prototype = {};

MyConstructor.prototype['foo'] = function() { alert('foo'); };
MyConstructor.prototype['bar'] = function() { alert('bar'); };
MyConstructor.prototype['baz'] = function() { alert('baz'); };

window['MyConstructor'] = MyConstructor;

}());

Ако поставите този код в Closure Compiler точно така, ето изхода (добре отпечатан):

function a() {
}
a.prototype = {};
a.prototype.foo = function() {
  alert("foo")
};
a.prototype.bar = function() {
  alert("bar")
};
a.prototype.baz = function() {
  alert("baz")
};
window.MyConstructor = a;

Въпросът е има ли някакъв начин да кажа на Closure Compiler, че е добре да обединявам всички тези в един обектен литерал и дори ако има код между тях (в този пример има t, но може да има), така че независимо от всичко, всичко това се компилира в един голям обектен литерал?

Ето няколко решения и защо те няма да работят за мен:

  • Решение 1: Просто ги декларирайте в един голям обектен литерал.
    Няма да работи, защото имам кода си в няколко файла и планирам да го направя така, че потребителите могат да премахнат някои от тях (ако не им трябват) преди компилация. Обектните литерали имат разделители със запетая, които биха превърнали това в кошмар.
  • Решение 2: Декларирайте цялата функционалност извън обекта (като частни променливи в затварянето) и ги прикачете в опростен обектен литерал в края, който има само препратки към свойства (като {'foo':foo,'bar':bar,'baz':baz}).
    Няма да работи, защото, както беше казано, идеята е да се създаде нещо модулно и премахването на един файл ще доведе до прекъсване на препратката.

Отворен съм за идеи!


Редактиране: Някои хора може да си помислят, че Closure Compiler не може да направи това. То може да направи това и много повече, просто има лоша нагласа и прави нещата, когато си иска.

Въведете това в Closure:

(function(){

var MyConstructor = window['MyConstructor'] = function() {};

var myProto = {
    'foo': function() { alert('foo'); },
    'bar': function() { alert('bar'); }
};

myProto['baz'] = function() { alert('baz'); };

MyConstructor.prototype = myProto;

}());

Резултатът е:

(window.MyConstructor = function() {
}).prototype = {foo:function() {
  alert("foo")
}, bar:function() {
  alert("bar")
}, baz:function() {
  alert("baz")
}};

виждаш ли Но този код е много крехък, тъй като може да се компилира в нещо напълно различно (и не толкова добро), ако се промени леко. Например дори присвояване на променлива някъде по средата може да доведе до извеждане на много различни резултати. С други думи, това не работи (освен в този случай).


Редактиране 2: вижте този jsperf. Голям обектен литерал е по-бърз в Chrome (пропорционално на неговия размер).


Редактиране 3: Доклад за грешка в Closure Compiler.


person Camilo Martin    schedule 30.09.2012    source източник
comment
@wvxvw Closure е много различен от обикновените минификатори, той наистина е компилатор. Прави неща, които надхвърлят това, което другите правят, поне с включен ADVANCED_OPTIMIZATIONS. Това, което имам предвид, е, че вече направи много други много по-сложни неща, които потенциално биха могли да нарушат моите javascripts сериозно (и понякога го направиха, за щастие имам модулни тестове, за да знам кога това се случва). Освен това има случай в моя код, когато Closure компилаторът ПРАВИ точно това! Ще редактирам с пример.   -  person Camilo Martin    schedule 30.09.2012
comment
@wvxvw Не е лошо. Има три режима на компилация. Единият премахва WHITESPACE_ONLY (супер безопасно), другият прави SIMPLE_OPTIMIZATIONS (нещо, което трябва да е безопасно в 99% от случаите, помислете за YUI компилатор), а това, което харесвам, е, когато прави ADVANCED_OPTIMIZATIONS, с други думи, има високо има вероятност да разбие кода ви, освен ако не сте много внимателни, но от друга страна, кодът работи по-бързо и е много по-малък от това, което може да направи вашият градински минификатор.   -  person Camilo Martin    schedule 30.09.2012
comment
Защо искате да бъде присвоен с помощта на синтаксис на единичен обектен литерал? Заради размера на файла ли е? Ако е така, копирате ли gzip? Ако сте, предполагам, че няма да има никаква разлика.   -  person I Hate Lazy    schedule 30.09.2012
comment
@user1689607 Аз архивирам (във всеки случай това е библиотека), но не е само заради размера на файла, трябва да има малко увеличение на производителността. Искам да кажа, сравнете създаването на празен обект и задаването на свойства върху него едно по едно срещу просто създаването му веднъж, с всички зададени свойства. Трябва да е по-бързо да го създадете само веднъж. Малко неофициален бенчмаркинг от моя страна изглежда потвърждава това в Chrome.   -  person Camilo Martin    schedule 30.09.2012
comment
@CamiloMartin: С цялото ми уважение, със сигурност ви вярвам, че директното сравнение на двата подхода показва, че присвояването на единичен обект е по-бързо от присвояването на празен обект, последвано от присвояване на множество свойства, но ако сравните цялото зареждане на дадената библиотека двата подхода, трудно бих повярвал, че разликата е осезаема. Ако това беше някакъв код, който трябваше да се изпълнява няколко пъти в бърза последователност, тези незначителни оптимизации може да си струват, но за еднократна операция не бих прекарал твърде много време в опити да надхитрим компилатора.   -  person I Hate Lazy    schedule 30.09.2012
comment
Не че се опитвам да омаловажа въпроса ви. Но прекарах достатъчно време, опитвайки се да настроя кода си за Closure Compiler, за да знам, че рядко има някаква реална разлика.   -  person I Hate Lazy    schedule 30.09.2012
comment
@user1689607 Е, мнението ти има смисъл, предполагам, че е малко инат. Ако не мога да намеря начин, ще се откажа от него и просто ще го направя прехвърляне на имоти.   -  person Camilo Martin    schedule 30.09.2012
comment
@wvxvw Имате предвид как работи jsPerf? Той изпълнява кода няколко пъти (като в този случай хиляди), така че прави повече или по-малко представителна средна стойност. Няма нужда да пишете самите бенчмарк цикли с jsPerf, тъй като той вече го прави. Може да искате да прочетете неговите често задавани въпроси или да проверите двигателя, който използва, Benchmark.js.   -  person Camilo Martin    schedule 01.10.2012
comment
@wvxvw Е, идеята е да се сравнят скоростите. Разбирам, че по-бързият код може да не е по-добър код (понякога може да има грешки или да е по-труден за поддържане), но е възможно да се измери неговата скорост. Той има предимството да бъде обективен показател, а обективността понякога се промъква на места, където качествената мярка би била по-добра. Няма да кажа, че това не е така с моите усилия за микрооптимизация...   -  person Camilo Martin    schedule 01.10.2012
comment
@wvxvw Добре, числото е в операции в секунда. Така че всеки фрагмент се изпълнява (евентуално с настройка/събиране) в цикъл, докато може да осредни някакъв стабилен брой операции в секунда. Колкото по-голямо е числото, толкова по-бързо се изпълнява кодът. Ако един елемент казва 10% по-бавен, това означава 10% по-бавен от най-бързия фрагмент - идеята е да сравните подобен код и да видите кой трябва да се използва въз основа на скоростта (ако приемем, че работят еднакво или са съвместими за определен случай).   -  person Camilo Martin    schedule 01.10.2012
comment
Вие сте прав, че компилаторът не прави тези оптимизации в момента. Можете ли да публикувате заявка за функция (и не забравяйте да посочите вашите jsperf резултати)? code.google.com/p/closure-compiler/issues/list   -  person Chad Killingsworth    schedule 01.10.2012
comment
@ChadKillingsworth Да, ще направя това и ще публикувам връзка тук.   -  person Camilo Martin    schedule 01.10.2012
comment
@wvxvw Е, не бих казал, че JsPerf е глупав - ако имате две части код (потенциално много голям код, ако включите библиотека), той лесно може да ви каже кой работи по-бързо. Това, което не разбирам, е защо казвате, че не ги сравнявате един с друг, за мен е така. Например резултат като този: 767,727 ±8.03% 61% slower означава, че определен фрагмент работи с около 767 727 операции в секунда, в рамките на 8% допустима грешка и е 61% по-бавен от най-бързия фрагмент.   -  person Camilo Martin    schedule 01.10.2012
comment
@wvxvw Е, по-бързо от другите фрагменти. Така че, ако знаете, че знаете пет начина да направите едно и също нещо, правите пет фрагмента и провеждате теста. Този, който казва най-бърз, е най-бързият. (Не мога да видя думата по-бързо в страницата, има само най-бързо и по-бавно).   -  person Camilo Martin    schedule 01.10.2012


Отговори (1)


Опитахте ли с ActiveDocument.Range.LanguageID = wdEnglishUS
person Camilo Martin    schedule 30.09.2012