.prototype
, .length
, offsetParent
and so on. Let's try to get rid of them using the example of the jQuery UI Sortable plugin. I’ll say right away that we don’t surpass gzip, but when it’s not at hand or impossible to use it (for example, at the 10K Apart competition), this compression technique can be very useful._mouseCapture()
:
- / *!
- * Source
- * /
- ( function ($) {
- var
- _mouseCapture = function ( event , overrideHandle) {
- if ( this .reverting) {
- return false ;
- }
- if ( this .options.disabled || this .options.type == 'static' ) return false ;
- // We have to refresh the items data once first
- this ._refreshItems ( event );
- // Find out if it’s clicked node (or one of its parents)
- var currentItem = null , self = this , nodes = $ ( event .target) .parents (). each ( function () {
- if ($ .data ( this , 'sortable-item' ) == self) {
- currentItem = $ ( this );
- return false ;
- }
- });
- if ($ .data ( event .target, 'sortable-item' ) == self) currentItem = $ ( event .target);
- if (! currentItem) return false ;
- if ( this .options.handle &&! overrideHandle) {
- var validHandle = false ;
- $ ( this .options.handle, currentItem) .find ( "*" ) .andSelf (). each ( function () { if ( this == event .target) validHandle = true ;}));
- if (! validHandle) return false ;
- }
- this .currentItem = currentItem;
- this ._removeCurrentsFromItems ();
- return true ;
- };
- }) (jQuery);
/*! <br> * <br> * , 576 <br> */ <br>( function (d){ var _mouseCapture= function (a,b){ if ( this .reverting) return false ; if ( this .options.disabled|| this .options.type== "static" ) return false ; this ._refreshItems(a); var c= null ,e= this ;d(a.target).parents().each( function (){ if (d.data( this , "sortable-item" )==e){c=d( this ); return false }}); if (d.data(a.target, "sortable-item" )==e)c=d(a.target); if (!c) return false ; if ( this .options.handle&&!b){ var f= false ;d( this .options.handle,c).find( "*" ).andSelf().each( function (){ if ( this ==a.target)f= true }); if (!f) return false } this .currentItem=c; this ._removeCurrentsFromItems(); return true }})(jQuery);
this
→ self
this
. In our initial plugin, it is used as many as 587 times (which is 2.3 KB or 6% of the code). Add a local variable self
to the beginning of the function:var <br> self = this ;<br>
this
function with self
and look at the results of compression.this .currentItem=e; this ._removeCurrentsFromItems();
d.currentItem=e;d._removeCurrentsFromItems();
/*! <br> * this > self <br> * YUI Compressor, 552 <br> */ <br>( function (b){ var a= function (f,g){ var d= this ; if (d.reverting){ return false } if (d.options.disabled||d.options.type== "static" ){ return false }d._refreshItems(f); var e= null ,c=b(f.target).parents().each( function (){ if (b.data( this , "sortable-item" )==d){e=b( this ); return false }}); if (b.data(f.target, "sortable-item" )==d){e=b(f.target)} if (!e){ return false } if (d.options.handle&&!g){ var h= false ;b(d.options.handle,e).find( "*" ).andSelf().each( function (){ if ( this ==f.target){h= true }}); if (!h){ return false }}d.currentItem=e;d._removeCurrentsFromItems(); return true }})(jQuery);
self = this
to transfer the context to the function being created, but for some reason it was not used for optimization. Here we just brought this announcement to the beginning, and in another function one could add, the extra few characters will pay off if at least 4 this
used in the function (and there are 70 of them).options
, target
, data
, "sortable-item"
and others are clearly visible. Most of them are object property names or strings, some occur 50–60 times in the original plugin. Compressors compress these elements (change names to shorter ones) only Closure Compiler is able in advanced mode, but here we see almost all the properties in their places. Most likely, when compiling the library, an extensive list of externals, incompressible names was given. There is a natural desire to correct this situation, because the method of optimization suggests the very syntax of the language. Let's make frequently used keys local variables:var <br> a = {<br> options: {<br> visible: true ,<br> mess: 'hi' <br> }<br> };
one:
if (a.options.visible) {<br> alert(a.options.mess);<br> a.options.visible = false ;<br>}
2:
var <br> o = 'options' ,<br> v = 'visible' ;<br> if (a[o][v]) {<br> alert(a[o].mess);<br> a[o][v] = false ;<br>}
visible
only once instead of two, and options
once instead of three. On the scale of a 40-kilobyte plug-in, and especially of the application, this gives a tangible gain in the amount of code (but not in clarity)./((\')|(\")|\.)\b([a-z_][\w-]+\w)\b(?(2)\')(?(3)\")/i
. For the original plug-in, 175 replacements were obtained, for the test one - 15:
- / *!
- * Replacing this> self
- * Replacing keys and strings
- * /
- ( function ($) {
- var
- _reverting = 'reverting' , // 3
- _options = 'options' , // 51
- _disabled = 'disabled' , // 4
- _type = 'type' , // 2
- _static = 'static' , // 2
- __refreshItems = '_refreshItems' , // 2
- _target = 'target' , // 4
- _parents = 'parents' , // 2
- _each = 'each' , // 5
- _data = 'data' , // 5
- _sortable_item = 'sortable-item' , // 6
- _handle = 'handle' , // 2
- _find = 'find' , // 2
- _currentItem = 'currentItem' , // 52
- FALSE =! 1, // 30
- TRUE =! 0, // 11
- _mouseCapture = function ( event , overrideHandle) {
- var
- self = this ;
- if (self [_reverting]) {
- return FALSE;
- }
- if (self [_options] [_ disabled] || self [_options] [_ type] == _static) return FALSE;
- self [__ refreshItems] ( event );
- var currentItem = null , nodes = $ ( event [_target]) [_ parents] () [_ each] ( function () {
- if ($ [_ data] ( this , _sortable_item) == self) {
- currentItem = $ ( this );
- return FALSE;
- }
- });
- if ($ [_ data] ( event [_target], _sortable_item) == self) currentItem = $ ( event [_target]);
- if (! currentItem) return FALSE;
- if (self [_options] [_ handle] &&! overrideHandle) {
- var validHandle = FALSE;
- $ (self [_options] [_ handle], currentItem) [_ find] ( "*" ) .andSelf () [_ each] ( function () { if ( this == event [_target]) validHandle = TRUE;});
- if (! validHandle) return FALSE;
- }
- self [_currentItem] = currentItem;
- self._removeCurrentsFromItems ();
- return TRUE;
- };
- }) (jQuery);
- / *!
- * Replacing this> self
- * Replacing keys and strings
- * YUI Compressor, 395 B + JS beautifier
- * /
- ( function (c) {
- var b = function (v, w) {
- var t = this ;
- if (t [e]) {
- return o
- }
- if (t [m] [k] || t [m] [r] == f) {
- return o
- }
- t [n] (v);
- var u = null ,
- s = c (v [i]) [g] () [q] ( function () {
- if (c [l] ( this , j) == t) {
- u = c ( this );
- return o
- }
- });
- if (c [l] (v [i], j) == t) {
- u = c (v [i])
- }
- if (! u) {
- return o
- }
- if (t [m] [d] &&! w) {
- var x = o;
- c (t [m] [d], u) [a] ( "*" ) .andSelf () [q] ( function () {
- if ( this == v [i]) {
- x = h
- }
- });
- if (! x) {
- return o
- }
- }
- t [p] = u;
- t._removeCurrentsFromItems ();
- return h
- }
- }) (jQuery);
document
, window
, etc.document
and window
not used, so we _mouseDrag()
temporarily turn to the neighboring _mouseDrag()
method:( function () {<br><br> if ( event .pageY - $( document ).scrollTop() < o.scrollSensitivity)<br> scrolled = $( document ).scrollTop($( document ).scrollTop() - o.scrollSpeed);<br> else if ($(window).height() - ( event .pageY - $( document ).scrollTop()) < o.scrollSensitivity)<br> scrolled = $( document ).scrollTop($( document ).scrollTop() + o.scrollSpeed);<br> <br> if ( event .pageX - $( document ).scrollLeft() < o.scrollSensitivity)<br> scrolled = $( document ).scrollLeft($( document ).scrollLeft() - o.scrollSpeed);<br> else if ($(window).width() - ( event .pageX - $( document ).scrollLeft()) < o.scrollSensitivity)<br> scrolled = $( document ).scrollLeft($( document ).scrollLeft() + o.scrollSpeed);<br><br>})();
( function () {<br> var g = document ,<br> f = window,<br> e = "scrollTop" ,<br> c = "scrollLeft" ,<br> b = "scrollSpeed" ,<br> d = "scrollSensitivity" ,<br> h = "pageY" ,<br> a = "pageX" ;<br><br> if ( event [h] - $(g)[e]() < o[d]) {<br> scrolled = $(g)[e]($(g)[e]() - o[b])<br> } else {<br> if ($(f).height() - ( event [h] - $(g)[e]()) < o[d]) {<br> scrolled = $(g)[e]($(g)[e]() + o[b])<br> }<br> }<br><br> if ( event [a] - $(g)[c]() < o[d]) {<br> scrolled = $(g)[c]($(g)[c]() - o[b])<br> } else {<br> if ($(f).width() - ( event [a] - $(g)[c]()) < o[d]) {<br> scrolled = $(g)[c]($(g)[c]() + o[b])<br> }<br> }<br><br>})();
var <br> doc = document ,<br> $doc = $(doc);
$( 'li' ).each( function (index, item) {<br> var <br> $item = $(item)<br> /* do something with $item */ <br>});
$( 'li' ).each( function (index, item, $item) {<br> /* do something with $item */ <br>});
/*! <br> * this > self <br> * <br> * YUI Compressor, 395 <br> */ <br>( function (c){ var b= function (v,w){ var t= this ; if (t[e]){ return o} if (t[m][k]||t[m][r]==f){ return o}t[n](v); var u= null ,s=c(v[i])[g]()[q]( function (){ if (c[l]( this ,j)==t){u=c( this ); return o}}); if (c[l](v[i],j)==t){u=c(v[i])} if (!u){ return o} if (t[m][d]&&!w){ var x=o;c(t[m][d],u)[a]( "*" ).andSelf()[q]( function (){ if ( this ==v[i]){x=h}}); if (!x){ return o}}t[p]=u;t._removeCurrentsFromItems(); return h}})(jQuery);
Source code | this → self | Property caching | |
Without compression | 39,495 | 40,241 | 41,148 |
YUI / CC | 23,656 | 22 185 | 18,496 |
gzip | 5 851 | 5,950 | 6,504 |
Source: https://habr.com/ru/post/100828/
All Articles