thisothree@JSDC
this• ‘the object’ it belongs in OOP
C++class Box {public:Box(double l=2.0, double b=2.0, double h=2.0) {this->length = l;this->breadth = b;this->height = h;}d...
Continued..int main(void){Box Box1(3.3, 1.2, 1.5);Box Box2(8.5, 6.0, 2.0);cout << Box1.Volume() << endl; // 3.3*1.2*1.5 = ...
this• Context in JavaScript• Can mean the object also
JavaScriptvar Box = function Box (l, b, h) {this.length = l;this.breadth = b;this.height = h;};Box.prototype.Volume = func...
this in Function• Context• Depends on how you call the function
3 Way to Call Functionvar big = function () {/*...*/};var foo = {small: function () {/*...*/}};big(); // 1. this: window o...
3 Way to Call Functionvar big = function () {/*...*/};var foo = {small: function () {/*...*/}};big(); // 1. this: window o...
Borrowing Methodvar foo = {small: function () {this;}};var bar = {};foo.small(); // this: foobar.borrowedSmall = foo.small...
this in Global Scope• Root object
Root Object• `window` in browsers• Root object in other environment
to Support Both(function () {root = this;//blah....}());
Strict Mode• No more global context
Don’t Forget `new`function Foobar() {"use strict";this.a = foo;this.b = bar;}var foobar1 = Foobar();// Cannot set property...
One More Way to CallFunction
apply/callvar foo = {};function foobar(v1, v2) {this.bar1 = v1;this.bar2 = v2;}foobar.call(foo, v1, v2); // this: foofooba...
bindvar foo = {};var otherFoo = {};function setBar(v1, v2) {this.bar1 = v1;this.bar2 = v2;}var fooSetBar = setBar.bind(foo...
ProtectYour Method• Bind context and function together
$.proxy/_.bind• Use apply to implement bind
Implement Bindvar bind = function (func, context) {return function () {func.apply(context, arguments);};};
Solve Event Handler• Use apply to assign context• JavaScript Libraries did it for you
this in Event Handler// W3C DomaElement.addEventListener(click, function () {this; // aElement}, false);// old IEaElement....
Callback Functionfunction Foobar (input) {this.prefix = input;}Foobar.prototype.echo = function (result) {return this.pref...
Reduce One Stackfunction Foobar (input) {this.prefix = input;}Foobar.prototype.echo = function (result) {return this.prefi...
Use bindfunction Foobar (input) {this.prefix = input;this.echo = this.echo.bind(this); // Protect method}Foobar.prototype....
Cons• Performance is bad• Old browser don’t support
Performancehttp://jsperf.com/bind-vs-closure-setup/10
Pros• Clearer code
Use _.bindfunction Foobar (input) {this.prefix = input;this.echo = _.bind(this.echo, this);// function, context}function F...
Use $.proxyfunction Foobar (input) {this.prefix = input;this.echo = $.proxy(this.echo, this);// function, context}function...
Bind by Needfb = new Foobar();$.get(/info, $.proxy(fb, echo));$.get(/info, $.proxy(fb.echo, fb));$.get(/info, $.bind(fb.ec...
http://www.flickr.com/photos/othree/8544069132/
Avoid Using this
Closurevar isIE = true;function foobar() {if (!isIE) {// access isIE is possible because of closurereturn;}// blah...};
that/selffunction Foobar(input) {var that = this; // that or selfthis.prefix = input;this.echo = function (result) {return...
CoffeeScript Fat ArrowFoobar = (input) ->@prefix = input@echo = (result) => @prefix + resultfb = new Foobar(res: )$.get(/i...
CoffeeScript Fat ArrowFoobar = (input) ->@prefix = input@echo = (result) => @prefix + resultfb = new Foobar(res: )$.get(/i...
Compile to JSvar Foobar, fb;Foobar = function(input) {var _this = this;this.prefix = input;return this.echo = function(res...
Compile to JSvar Foobar, fb;Foobar = function(input) {var _this = this;this.prefix = input;return this.echo = function(res...
Compile to JSvar Foobar, fb;Foobar = function(input) {var _this = this;this.prefix = input;return this.echo = function(res...
LiveScript use ~>
Pros• No more this issue, context free• Reduce one call stack• No call/apply, no impact on performance• Encapsulation
Cons• Can’t use this tip on normal constructor
How about AMD• Define modules can return constructor,function, array, primitive data• Define a singleton module on most case...
AMD Singleton Moduledefine(foobar, function () {return {init: function (prefix) {this.prefix = prefix;}echo: function (inp...
Cons• Function can be borrowed• Not doing on right `this` you expect
Avoid Use thisdefine(foobar, function () {var self = {};return {init: function (prefix) {self.prefix = prefix;}echo: funct...
Constructors?• Use bind to protect methods if necessary
Constructor Withoutthisfunction Person(birth, gender) {var person = {birth: (birth || 1970/01/01),gender: (gender || M)};r...
to new or not to newvar p1 = Person(2013/01/02);p1.getBirth(); // "2013/01/02"var p2 = new Person(2000/01/02, F);p2.getBir...
Cons• No prototype inheritance• More memory usage for methods
Backbone Modeldefine(function (require) {return Backbone.Model.extend(initialize: function (attrs) {return _.bindAll(this)...
Who Use this Tip• jQuery.Deferred• jQuery.Callbacks
Deferred Chainingvar firstDfd = $.Deferred(),secondDfd = $.Deferred(),thirdDfd = $.Deferred();firstDfd.done(secondDfd.reso...
Callbackshttps://github.com/jquery/jquery/blob/master/src/deferred.js// promise[ done | fail | progress ] = list.addpromis...
Callbackshttps://github.com/jquery/jquery/blob/master/src/deferred.js// promise[ done | fail | progress ] = list.addpromis...
Actually Arepromise[done] = resolveCallbacks.add;promise[fail] = rejectCallbacks.add;promise[progress] = notifyCallbacks.a...
Summary• Understand `this`• Understand how not to use `this`• Use `this` carefully if necessary
Trade-Off• ‘Not use this’ requires more memory onmethods definition and not easy toinheritance object• Benefit is you can wr...
References
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/this
Questions?http://www.flickr.com/photos/roman/5610736/
this
Upcoming SlideShare
Loading in...5
×

this

525

Published on

Explain this of JavaScript

Published in: Technology
0 Comments
6 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
525
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
10
Comments
0
Likes
6
Embeds 0
No embeds

No notes for slide

this

  1. 1. thisothree@JSDC
  2. 2. this• ‘the object’ it belongs in OOP
  3. 3. C++class Box {public:Box(double l=2.0, double b=2.0, double h=2.0) {this->length = l;this->breadth = b;this->height = h;}double Volume() {return length * breadth * height;}int compare(Box box) {return this->Volume() > box.Volume();}private:double length;double breadth;double height;};
  4. 4. Continued..int main(void){Box Box1(3.3, 1.2, 1.5);Box Box2(8.5, 6.0, 2.0);cout << Box1.Volume() << endl; // 3.3*1.2*1.5 = 5.94cout << Box2.Volume() << endl; // 8.5*6.0*2.0 = 102return 0;}
  5. 5. this• Context in JavaScript• Can mean the object also
  6. 6. JavaScriptvar Box = function Box (l, b, h) {this.length = l;this.breadth = b;this.height = h;};Box.prototype.Volume = function () {return this.length * this.breadth * this.height;};Box.prototype.compare = function (box) {return this.Volume() > box.Volume();};
  7. 7. this in Function• Context• Depends on how you call the function
  8. 8. 3 Way to Call Functionvar big = function () {/*...*/};var foo = {small: function () {/*...*/}};big(); // 1. this: window objectfoo.small(); // 2. this: foovar small = foo.small;small();
  9. 9. 3 Way to Call Functionvar big = function () {/*...*/};var foo = {small: function () {/*...*/}};big(); // 1. this: window objectfoo.small(); // 2. this: foovar small = foo.small;small(); // 3. this: window object
  10. 10. Borrowing Methodvar foo = {small: function () {this;}};var bar = {};foo.small(); // this: foobar.borrowedSmall = foo.small;bar.borrowedSmall(); // this: bar
  11. 11. this in Global Scope• Root object
  12. 12. Root Object• `window` in browsers• Root object in other environment
  13. 13. to Support Both(function () {root = this;//blah....}());
  14. 14. Strict Mode• No more global context
  15. 15. Don’t Forget `new`function Foobar() {"use strict";this.a = foo;this.b = bar;}var foobar1 = Foobar();// Cannot set property a of undefinedvar foobar2 = new Foobar();// this: new empty object
  16. 16. One More Way to CallFunction
  17. 17. apply/callvar foo = {};function foobar(v1, v2) {this.bar1 = v1;this.bar2 = v2;}foobar.call(foo, v1, v2); // this: foofoobar.apply(foo, [v1, v2]); // this: foo
  18. 18. bindvar foo = {};var otherFoo = {};function setBar(v1, v2) {this.bar1 = v1;this.bar2 = v2;}var fooSetBar = setBar.bind(foo);fooSetBar(1, 2); // this: foootherFoo.foobar = fooSetBar;otherFoo.foobar(3, 4); // this: foo
  19. 19. ProtectYour Method• Bind context and function together
  20. 20. $.proxy/_.bind• Use apply to implement bind
  21. 21. Implement Bindvar bind = function (func, context) {return function () {func.apply(context, arguments);};};
  22. 22. Solve Event Handler• Use apply to assign context• JavaScript Libraries did it for you
  23. 23. this in Event Handler// W3C DomaElement.addEventListener(click, function () {this; // aElement}, false);// old IEaElement.attachEvent(onclick, function () {this; // window});
  24. 24. Callback Functionfunction Foobar (input) {this.prefix = input;}Foobar.prototype.echo = function (result) {return this.prefix + result;};fb = new Foobar();$.get(/info, function (result) {fb.echo(result);});
  25. 25. Reduce One Stackfunction Foobar (input) {this.prefix = input;}Foobar.prototype.echo = function (result) {return this.prefix + result;};fb = new Foobar();$.get(/info, fb.echo); // this.prefix is undefined
  26. 26. Use bindfunction Foobar (input) {this.prefix = input;this.echo = this.echo.bind(this); // Protect method}Foobar.prototype.echo = function (result) {return this.prefix + result;};fb = new Foobar();$.get(/info, fb.echo);
  27. 27. Cons• Performance is bad• Old browser don’t support
  28. 28. Performancehttp://jsperf.com/bind-vs-closure-setup/10
  29. 29. Pros• Clearer code
  30. 30. Use _.bindfunction Foobar (input) {this.prefix = input;this.echo = _.bind(this.echo, this);// function, context}function Foobar (input) {this.prefix = input;_.bindAll(this);// context}http://underscorejs.org/#bind
  31. 31. Use $.proxyfunction Foobar (input) {this.prefix = input;this.echo = $.proxy(this.echo, this);// function, context}function Foobar (input) {this.prefix = input;this.echo = $.proxy(this, echo);// context, method name}http://api.jquery.com/jQuery.proxy/
  32. 32. Bind by Needfb = new Foobar();$.get(/info, $.proxy(fb, echo));$.get(/info, $.proxy(fb.echo, fb));$.get(/info, $.bind(fb.echo, fb));
  33. 33. http://www.flickr.com/photos/othree/8544069132/
  34. 34. Avoid Using this
  35. 35. Closurevar isIE = true;function foobar() {if (!isIE) {// access isIE is possible because of closurereturn;}// blah...};
  36. 36. that/selffunction Foobar(input) {var that = this; // that or selfthis.prefix = input;this.echo = function (result) {return that.prefix + result;// that is accessible because of closure};}fb = new Foobar(res: );$.get(/info, fb.echo);
  37. 37. CoffeeScript Fat ArrowFoobar = (input) ->@prefix = input@echo = (result) => @prefix + resultfb = new Foobar(res: )$.get(/info, fb.echo)
  38. 38. CoffeeScript Fat ArrowFoobar = (input) ->@prefix = input@echo = (result) => @prefix + resultfb = new Foobar(res: )$.get(/info, fb.echo)
  39. 39. Compile to JSvar Foobar, fb;Foobar = function(input) {var _this = this;this.prefix = input;return this.echo = function(result) {return _this.prefix + result;};};fb = new Foobar(res: );$.get(/info, fb.echo);
  40. 40. Compile to JSvar Foobar, fb;Foobar = function(input) {var _this = this;this.prefix = input;return this.echo = function(result) {return _this.prefix + result;};};fb = new Foobar(res: );$.get(/info, fb.echo);
  41. 41. Compile to JSvar Foobar, fb;Foobar = function(input) {var _this = this;this.prefix = input;return this.echo = function(result) {return _this.prefix + result;};};fb = new Foobar(res: );$.get(/info, fb.echo);
  42. 42. LiveScript use ~>
  43. 43. Pros• No more this issue, context free• Reduce one call stack• No call/apply, no impact on performance• Encapsulation
  44. 44. Cons• Can’t use this tip on normal constructor
  45. 45. How about AMD• Define modules can return constructor,function, array, primitive data• Define a singleton module on most cases• Always have data on module
  46. 46. AMD Singleton Moduledefine(foobar, function () {return {init: function (prefix) {this.prefix = prefix;}echo: function (input) {return this.prefix + input;}};});
  47. 47. Cons• Function can be borrowed• Not doing on right `this` you expect
  48. 48. Avoid Use thisdefine(foobar, function () {var self = {};return {init: function (prefix) {self.prefix = prefix;}echo: function (input) {return self.prefix + input;}};});
  49. 49. Constructors?• Use bind to protect methods if necessary
  50. 50. Constructor Withoutthisfunction Person(birth, gender) {var person = {birth: (birth || 1970/01/01),gender: (gender || M)};return {getBirth: function () {return person.birth;},getGender: function () {return person.gender;}};}
  51. 51. to new or not to newvar p1 = Person(2013/01/02);p1.getBirth(); // "2013/01/02"var p2 = new Person(2000/01/02, F);p2.getBirth(); // "2000/01/02"p1.getBirth(); // "2013/01/02"
  52. 52. Cons• No prototype inheritance• More memory usage for methods
  53. 53. Backbone Modeldefine(function (require) {return Backbone.Model.extend(initialize: function (attrs) {return _.bindAll(this);},toITEM: function () {return this.toJSON();},toConfig: function () {return {name: this.get(name),package_name: this.get(package_name)};});});
  54. 54. Who Use this Tip• jQuery.Deferred• jQuery.Callbacks
  55. 55. Deferred Chainingvar firstDfd = $.Deferred(),secondDfd = $.Deferred(),thirdDfd = $.Deferred();firstDfd.done(secondDfd.resolve);secondDfd.done(thirdDfd.resolve);firstDfd.resolve(); // All Deferred object resolved here
  56. 56. Callbackshttps://github.com/jquery/jquery/blob/master/src/deferred.js// promise[ done | fail | progress ] = list.addpromise[ tuple[1] ] = list.add;// skip...// deferred[ resolve | reject | notify ]deferred[ tuple[0] ] = function() {deferred[ tuple[0] + "With" ](this === deferred ? promise : this, arguments);return this;};deferred[ tuple[0] + "With" ] = list.fireWith;
  57. 57. Callbackshttps://github.com/jquery/jquery/blob/master/src/deferred.js// promise[ done | fail | progress ] = list.addpromise[ tuple[1] ] = list.add;// skip...// deferred[ resolve | reject | notify ]deferred[ tuple[0] ] = function() {deferred[ tuple[0] + "With" ](this === deferred ? promise : this, arguments);return this;};deferred[ tuple[0] + "With" ] = list.fireWith;
  58. 58. Actually Arepromise[done] = resolveCallbacks.add;promise[fail] = rejectCallbacks.add;promise[progress] = notifyCallbacks.add;// skip...deferred["resolveWith"] = resolveCallbacks.fireWith;deferred["rejectWith"] = rejectCallbacks.fireWith;deferred["notifyWith"] = notifyCallbacks.fireWith;
  59. 59. Summary• Understand `this`• Understand how not to use `this`• Use `this` carefully if necessary
  60. 60. Trade-Off• ‘Not use this’ requires more memory onmethods definition and not easy toinheritance object• Benefit is you can write more clear, simplecode
  61. 61. References
  62. 62. https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/this
  63. 63. Questions?http://www.flickr.com/photos/roman/5610736/
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×