I find this pattern all over the ExtJS source code.
method: function() {
var me = this;
...
me.someOtherMethod();
}
Why don't they just use this
? Is there some advantage to always often defining me
(outside of not having to type 2 characters)? I can understand if they are trying to maintain th开发者_StackOverflow社区e context via closure, but it's done in places where there is no closure at all.
An example from Ext.panel.Panel:
disable: function(silent) {
var me = this;
if (me.rendered) {
me.el.addCls(me.disabledCls);
me.el.dom.disabled = true;
me.onDisable();
}
me.disabled = true;
if (silent !== true) {
me.fireEvent('disable', me);
}
return me;
},
If your library is doing this in places where there are no embedded closures/callbacks that might have their own value of this
, then this is just a "practice" or "style" or "convention" that they decided to follow in their methods. There is NO programming reason to always do it.
In the specific coding example you have now added to your question, there is no reason I'm aware of other than a common coding style. This code would generate the same result in slightly smaller code:
disable: function(silent) {
if (this.rendered) {
this.el.addCls(this.disabledCls);
this.el.dom.disabled = true;
this.onDisable();
}
this.disabled = true;
if (silent !== true) {
this.fireEvent('disable', this);
}
return this;
},
When there is a callback or closure involved, this is often done because there are callbacks used inside the method where they still want a reference to this
, but those callbacks will have their own value of this
so assigning:
var me = this;
or more commonly in other code I've seen:
var self = this;
is a way of retaining access to that object even in a callback that has a different value of this
.
Here's a generic example:
document.getElementById("myButton").onclick = function () {
var self = this; // save reference to button object use later
setTimeout(function() {
// "this" is not set to the button inside this callback function (it's set to window)
// but, we can access "self" here
self.style.display = "none"; // make button disappear 2 seconds after it was clicked
}, 2000);
};
One reason is because with minification, me
can become much shorter than this
.
Besides the style reasons and the minification reasons, I decided to look at performance to see if this
or self
was any faster. I created this jsperf test.
As best I can tell, there is basically no difference in performance in any of the modern browsers that I tried or even IE6 bewtween using this
vs. using a local variable like self
or me
. Chrome is ever so slightly faster with self
and the others are too close to call. I think we can rule out any performance reasons. Here's a screen shot of the results I saw:
The problem is most likely connected to closure functions, for example as an argument when you register an callback. In that case "this" can have a whole different value, so they need to use "me" instead.
It's done sometimes to maintain scope in a closure, but mostly (as in the posted example) to allow for minification as me
can be minified down to one character, while this
cannot be changed. After about 3 or 4 usages of this
in a given function this becomes important (less than that and you might actually end up with a few extra bytes from the extra declaration code). It's as simple as that -- it has nothing to do with programming style or whimsy.
Based on the Ext.panel.Panel
example you just added, unless my understanding of Javascript variables is quite wrong, not making the assignment here would have absolutely no impact on what the code does.
The only possibility left is style.
While I would chalk this up as overengineering, it's useful to the extent that if you ever wanted to add a callback that required access to this
in this context, you wouldn't need to go back to change all the this
's to me
's. After all, typing :s/
is hard.
Actually, though it probably isn't the motivation, doing this for style makes some sense. A lot of style conventions are to make it harder to forget something, such as always putting { } around an else block even if it's a single statement. Reassigning "this" would have a similar affect in that beginning JavaScript programmers would have closures "just work" a higher percentage of the time.
Outside of maintaining a context for use in closures I am not aware of any programmatic difference with using that pattern. Perhaps it is just a convention ExtJS is using.
Additionally, as noted by Daniel, it might be to shorten the code even further during minification. Libraries like ExtJS, jQuery, etc care a lot about file sizes and using this technique might yield enough file size savings
e.g. 1000 'this', assuming 1 char = 1 byte, is 4kb. Using the technique above can possibly shave off 2 or 3 kb.
update: Went ahead and did a small experiment..
var test = {
a : function() {
this.x='';
this.x='';
this.x='';
this.x='';
this.x='';
this.x='';
this.x='';
this.x='';
this.x='';
this.x='';
this.x='';
this.x='';
},
b : function() {
this.x='';
this.x='';
this.x='';
this.x='';
this.x='';
this.x='';
this.x='';
this.x='';
this.x='';
this.x='';
this.x='';
this.x='';
},
c : function() {
this.x='';
this.x='';
this.x='';
this.x='';
this.x='';
this.x='';
this.x='';
this.x='';
this.x='';
this.x='';
this.x='';
this.x='';
}
}
minifies into
var test={a:function(){this.x="";this.x="";this.x="";this.x="";this.x="";this.x="";this.x="";this.x="";this.x="";this.x="";this.x="";this.x=""},b:function(){this.x="";this.x="";this.x="";this.x="";this.x="";this.x="";this.x="";this.x="";this.x="";this.x="";this.x="";this.x=""},c:function(){this.x="";this.x="";this.x="";this.x="";this.x="";this.x="";this.x="";this.x="";this.x="";this.x="";this.x="";this.x=""}}
while
var test = {
a : function() {
var me=this;
me.x='';
me.x='';
me.x='';
me.x='';
me.x='';
me.x='';
me.x='';
me.x='';
me.x='';
me.x='';
me.x='';
me.x='';
},
b : function() {
var me=this;
me.x='';
me.x='';
me.x='';
me.x='';
me.x='';
me.x='';
me.x='';
me.x='';
me.x='';
me.x='';
me.x='';
me.x='';
},
c : function() {
var me=this;
me.x='';
me.x='';
me.x='';
me.x='';
me.x='';
me.x='';
me.x='';
me.x='';
me.x='';
me.x='';
me.x='';
me.x='';
}
}
minifies into
var test={a:function(){var a=this;a.x="";a.x="";a.x="";a.x="";a.x="";a.x="";a.x="";a.x="";a.x="";a.x="";a.x="";a.x=""},b:function(){var a=this;a.x="";a.x="";a.x="";a.x="";a.x="";a.x="";a.x="";a.x="";a.x="";a.x="";a.x="";a.x=""},c:function(){var a=this;a.x="";a.x="";a.x="";a.x="";a.x="";a.x="";a.x="";a.x="";a.x="";a.x="";a.x="";a.x=""}}
which translates to about 10% more or less characters(of course it depends on how much 'this' is used repetitively in the block scopes of your code).
For the ExtJS framework specifically.
ExtJS has it's own mechanisms for handling problematic Javascript scoping, minification is the only reason for doing var me = this
.
There are more details on the subject in this Sencha Forum thread.
While working ExtJs I didn't find this convention that useful. I didn't use closures very often. When working in other frameworks like AngularJs this convention has saved me much pain and suffering. Getting your scope wrong is a time consuming bug to track down. Once I started to use this convention, I never got the scope wrong again.
精彩评论