this

  • 432 views
Uploaded on

Explain this of JavaScript

Explain this of JavaScript

More in: Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
432
On Slideshare
0
From Embeds
0
Number of Embeds
0

Actions

Shares
Downloads
8
Comments
0
Likes
6

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. thisothree@JSDC
  • 2. this• ‘the object’ it belongs in OOP
  • 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. 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. this• Context in JavaScript• Can mean the object also
  • 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. this in Function• Context• Depends on how you call the function
  • 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. 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. Borrowing Methodvar foo = {small: function () {this;}};var bar = {};foo.small(); // this: foobar.borrowedSmall = foo.small;bar.borrowedSmall(); // this: bar
  • 11. this in Global Scope• Root object
  • 12. Root Object• `window` in browsers• Root object in other environment
  • 13. to Support Both(function () {root = this;//blah....}());
  • 14. Strict Mode• No more global context
  • 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. One More Way to CallFunction
  • 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. 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. ProtectYour Method• Bind context and function together
  • 20. $.proxy/_.bind• Use apply to implement bind
  • 21. Implement Bindvar bind = function (func, context) {return function () {func.apply(context, arguments);};};
  • 22. Solve Event Handler• Use apply to assign context• JavaScript Libraries did it for you
  • 23. this in Event Handler// W3C DomaElement.addEventListener(click, function () {this; // aElement}, false);// old IEaElement.attachEvent(onclick, function () {this; // window});
  • 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. 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. 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. Cons• Performance is bad• Old browser don’t support
  • 28. Performancehttp://jsperf.com/bind-vs-closure-setup/10
  • 29. Pros• Clearer code
  • 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. 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. Bind by Needfb = new Foobar();$.get(/info, $.proxy(fb, echo));$.get(/info, $.proxy(fb.echo, fb));$.get(/info, $.bind(fb.echo, fb));
  • 33. http://www.flickr.com/photos/othree/8544069132/
  • 34. Avoid Using this
  • 35. Closurevar isIE = true;function foobar() {if (!isIE) {// access isIE is possible because of closurereturn;}// blah...};
  • 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. CoffeeScript Fat ArrowFoobar = (input) ->@prefix = input@echo = (result) => @prefix + resultfb = new Foobar(res: )$.get(/info, fb.echo)
  • 38. CoffeeScript Fat ArrowFoobar = (input) ->@prefix = input@echo = (result) => @prefix + resultfb = new Foobar(res: )$.get(/info, fb.echo)
  • 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. 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. 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. LiveScript use ~>
  • 43. Pros• No more this issue, context free• Reduce one call stack• No call/apply, no impact on performance• Encapsulation
  • 44. Cons• Can’t use this tip on normal constructor
  • 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. AMD Singleton Moduledefine(foobar, function () {return {init: function (prefix) {this.prefix = prefix;}echo: function (input) {return this.prefix + input;}};});
  • 47. Cons• Function can be borrowed• Not doing on right `this` you expect
  • 48. Avoid Use thisdefine(foobar, function () {var self = {};return {init: function (prefix) {self.prefix = prefix;}echo: function (input) {return self.prefix + input;}};});
  • 49. Constructors?• Use bind to protect methods if necessary
  • 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. 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. Cons• No prototype inheritance• More memory usage for methods
  • 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. Who Use this Tip• jQuery.Deferred• jQuery.Callbacks
  • 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. 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. 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. 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. Summary• Understand `this`• Understand how not to use `this`• Use `this` carefully if necessary
  • 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. References
  • 62. https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/this
  • 63. Questions?http://www.flickr.com/photos/roman/5610736/