Download - this
![Page 1: this](https://reader034.vdocuments.us/reader034/viewer/2022042814/5558bd86d8b42aa52a8b5042/html5/thumbnails/1.jpg)
this
othree@JSDC
![Page 2: this](https://reader034.vdocuments.us/reader034/viewer/2022042814/5558bd86d8b42aa52a8b5042/html5/thumbnails/2.jpg)
![Page 3: this](https://reader034.vdocuments.us/reader034/viewer/2022042814/5558bd86d8b42aa52a8b5042/html5/thumbnails/3.jpg)
this
• ‘the object’ it belongs in OOP
![Page 4: this](https://reader034.vdocuments.us/reader034/viewer/2022042814/5558bd86d8b42aa52a8b5042/html5/thumbnails/4.jpg)
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;};
![Page 5: this](https://reader034.vdocuments.us/reader034/viewer/2022042814/5558bd86d8b42aa52a8b5042/html5/thumbnails/5.jpg)
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.94 cout << Box2.Volume() << endl; // 8.5*6.0*2.0 = 102 return 0;}
![Page 6: this](https://reader034.vdocuments.us/reader034/viewer/2022042814/5558bd86d8b42aa52a8b5042/html5/thumbnails/6.jpg)
this
• Context in JavaScript
• Can mean the object also
![Page 7: this](https://reader034.vdocuments.us/reader034/viewer/2022042814/5558bd86d8b42aa52a8b5042/html5/thumbnails/7.jpg)
JavaScript
var 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();};
![Page 8: this](https://reader034.vdocuments.us/reader034/viewer/2022042814/5558bd86d8b42aa52a8b5042/html5/thumbnails/8.jpg)
this in Function
• Context
• Depends on how you call the function
![Page 9: this](https://reader034.vdocuments.us/reader034/viewer/2022042814/5558bd86d8b42aa52a8b5042/html5/thumbnails/9.jpg)
3 Way to Call Function
var big = function () {/*...*/};
var foo = { small: function () {/*...*/}};
big(); // 1. this: window objectfoo.small(); // 2. this: foo
var small = foo.small;small();
![Page 10: this](https://reader034.vdocuments.us/reader034/viewer/2022042814/5558bd86d8b42aa52a8b5042/html5/thumbnails/10.jpg)
3 Way to Call Function
var big = function () {/*...*/};
var foo = { small: function () {/*...*/}};
big(); // 1. this: window objectfoo.small(); // 2. this: foo
var small = foo.small;small(); // 3. this: window object
![Page 11: this](https://reader034.vdocuments.us/reader034/viewer/2022042814/5558bd86d8b42aa52a8b5042/html5/thumbnails/11.jpg)
Borrowing Method
var foo = { small: function () { this; }};var bar = {};
foo.small(); // this: foo
bar.borrowedSmall = foo.small;bar.borrowedSmall(); // this: bar
![Page 12: this](https://reader034.vdocuments.us/reader034/viewer/2022042814/5558bd86d8b42aa52a8b5042/html5/thumbnails/12.jpg)
this in Global Scope
• Root object
![Page 13: this](https://reader034.vdocuments.us/reader034/viewer/2022042814/5558bd86d8b42aa52a8b5042/html5/thumbnails/13.jpg)
Root Object
• `window` in browsers
• Root object in other environment
![Page 14: this](https://reader034.vdocuments.us/reader034/viewer/2022042814/5558bd86d8b42aa52a8b5042/html5/thumbnails/14.jpg)
to Support Both
(function () { root = this; //blah....}());
![Page 15: this](https://reader034.vdocuments.us/reader034/viewer/2022042814/5558bd86d8b42aa52a8b5042/html5/thumbnails/15.jpg)
Strict Mode
• No more global context
![Page 16: this](https://reader034.vdocuments.us/reader034/viewer/2022042814/5558bd86d8b42aa52a8b5042/html5/thumbnails/16.jpg)
Don’t Forget `new`
function Foobar() { "use strict"; this.a = 'foo'; this.b = 'bar';} var foobar1 = Foobar();// Cannot set property 'a' of undefined
var foobar2 = new Foobar();// this: new empty object
![Page 17: this](https://reader034.vdocuments.us/reader034/viewer/2022042814/5558bd86d8b42aa52a8b5042/html5/thumbnails/17.jpg)
One More Way to Call Function
![Page 18: this](https://reader034.vdocuments.us/reader034/viewer/2022042814/5558bd86d8b42aa52a8b5042/html5/thumbnails/18.jpg)
apply/call
var foo = {};
function foobar(v1, v2) { this.bar1 = v1; this.bar2 = v2;}
foobar.call(foo, v1, v2); // this: foofoobar.apply(foo, [v1, v2]); // this: foo
![Page 19: this](https://reader034.vdocuments.us/reader034/viewer/2022042814/5558bd86d8b42aa52a8b5042/html5/thumbnails/19.jpg)
bindvar foo = {};var otherFoo = {};
function setBar(v1, v2) { this.bar1 = v1; this.bar2 = v2;}
var fooSetBar = setBar.bind(foo);
fooSetBar(1, 2); // this: foo
otherFoo.foobar = fooSetBar;otherFoo.foobar(3, 4); // this: foo
![Page 20: this](https://reader034.vdocuments.us/reader034/viewer/2022042814/5558bd86d8b42aa52a8b5042/html5/thumbnails/20.jpg)
Protect Your Method
• Bind context and function together
![Page 21: this](https://reader034.vdocuments.us/reader034/viewer/2022042814/5558bd86d8b42aa52a8b5042/html5/thumbnails/21.jpg)
$.proxy/_.bind
• Use apply to implement bind
![Page 22: this](https://reader034.vdocuments.us/reader034/viewer/2022042814/5558bd86d8b42aa52a8b5042/html5/thumbnails/22.jpg)
Implement Bind
var bind = function (func, context) { return function () { func.apply(context, arguments); };};
![Page 23: this](https://reader034.vdocuments.us/reader034/viewer/2022042814/5558bd86d8b42aa52a8b5042/html5/thumbnails/23.jpg)
Solve Event Handler
• Use apply to assign context
• JavaScript Libraries did it for you
![Page 24: this](https://reader034.vdocuments.us/reader034/viewer/2022042814/5558bd86d8b42aa52a8b5042/html5/thumbnails/24.jpg)
this in Event Handler
// W3C DomaElement.addEventListener('click', function () { this; // aElement}, false);
// old IEaElement.attachEvent('onclick', function () { this; // window});
![Page 25: this](https://reader034.vdocuments.us/reader034/viewer/2022042814/5558bd86d8b42aa52a8b5042/html5/thumbnails/25.jpg)
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);});
![Page 26: this](https://reader034.vdocuments.us/reader034/viewer/2022042814/5558bd86d8b42aa52a8b5042/html5/thumbnails/26.jpg)
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'
![Page 27: this](https://reader034.vdocuments.us/reader034/viewer/2022042814/5558bd86d8b42aa52a8b5042/html5/thumbnails/27.jpg)
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);
![Page 28: this](https://reader034.vdocuments.us/reader034/viewer/2022042814/5558bd86d8b42aa52a8b5042/html5/thumbnails/28.jpg)
Cons
• Performance is bad
• Old browser don’t support
![Page 29: this](https://reader034.vdocuments.us/reader034/viewer/2022042814/5558bd86d8b42aa52a8b5042/html5/thumbnails/29.jpg)
Performance
http://jsperf.com/bind-vs-closure-setup/10
![Page 30: this](https://reader034.vdocuments.us/reader034/viewer/2022042814/5558bd86d8b42aa52a8b5042/html5/thumbnails/30.jpg)
Pros
• Clearer code
![Page 31: this](https://reader034.vdocuments.us/reader034/viewer/2022042814/5558bd86d8b42aa52a8b5042/html5/thumbnails/31.jpg)
Use _.bind
function 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
![Page 32: this](https://reader034.vdocuments.us/reader034/viewer/2022042814/5558bd86d8b42aa52a8b5042/html5/thumbnails/32.jpg)
Use $.proxy
function 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/
![Page 33: this](https://reader034.vdocuments.us/reader034/viewer/2022042814/5558bd86d8b42aa52a8b5042/html5/thumbnails/33.jpg)
Bind by Need
fb = new Foobar();
$.get('/info', $.proxy(fb, 'echo'));$.get('/info', $.proxy(fb.echo, fb));
$.get('/info', $.bind(fb.echo, fb));
![Page 34: this](https://reader034.vdocuments.us/reader034/viewer/2022042814/5558bd86d8b42aa52a8b5042/html5/thumbnails/34.jpg)
http://www.flickr.com/photos/othree/8544069132/
![Page 35: this](https://reader034.vdocuments.us/reader034/viewer/2022042814/5558bd86d8b42aa52a8b5042/html5/thumbnails/35.jpg)
Avoid Using this
![Page 36: this](https://reader034.vdocuments.us/reader034/viewer/2022042814/5558bd86d8b42aa52a8b5042/html5/thumbnails/36.jpg)
Closure
var isIE = true;
function foobar() { if (!isIE) { // access isIE is possible because of closure return; } // blah...};
![Page 37: this](https://reader034.vdocuments.us/reader034/viewer/2022042814/5558bd86d8b42aa52a8b5042/html5/thumbnails/37.jpg)
that/selffunction Foobar(input) { var that = this; // that or self this.prefix = input; this.echo = function (result) { return that.prefix + result; // that is accessible because of closure };}
fb = new Foobar('res: ');
$.get('/info', fb.echo);
![Page 38: this](https://reader034.vdocuments.us/reader034/viewer/2022042814/5558bd86d8b42aa52a8b5042/html5/thumbnails/38.jpg)
CoffeeScript Fat Arrow
Foobar = (input) -> @prefix = input @echo = (result) => @prefix + result fb = new Foobar('res: ')
$.get('/info', fb.echo)
![Page 39: this](https://reader034.vdocuments.us/reader034/viewer/2022042814/5558bd86d8b42aa52a8b5042/html5/thumbnails/39.jpg)
CoffeeScript Fat Arrow
Foobar = (input) -> @prefix = input @echo = (result) => @prefix + result fb = new Foobar('res: ')
$.get('/info', fb.echo)
![Page 40: this](https://reader034.vdocuments.us/reader034/viewer/2022042814/5558bd86d8b42aa52a8b5042/html5/thumbnails/40.jpg)
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);
![Page 41: this](https://reader034.vdocuments.us/reader034/viewer/2022042814/5558bd86d8b42aa52a8b5042/html5/thumbnails/41.jpg)
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);
![Page 42: this](https://reader034.vdocuments.us/reader034/viewer/2022042814/5558bd86d8b42aa52a8b5042/html5/thumbnails/42.jpg)
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);
![Page 43: this](https://reader034.vdocuments.us/reader034/viewer/2022042814/5558bd86d8b42aa52a8b5042/html5/thumbnails/43.jpg)
LiveScript use ~>
![Page 44: this](https://reader034.vdocuments.us/reader034/viewer/2022042814/5558bd86d8b42aa52a8b5042/html5/thumbnails/44.jpg)
Pros
• No more this issue, context free
• Reduce one call stack
• No call/apply, no impact on performance
• Encapsulation
![Page 45: this](https://reader034.vdocuments.us/reader034/viewer/2022042814/5558bd86d8b42aa52a8b5042/html5/thumbnails/45.jpg)
Cons
• Can’t use this tip on normal constructor
![Page 46: this](https://reader034.vdocuments.us/reader034/viewer/2022042814/5558bd86d8b42aa52a8b5042/html5/thumbnails/46.jpg)
How about AMD
• Define modules can return constructor, function, array, primitive data
• Define a singleton module on most cases
• Always have data on module
![Page 47: this](https://reader034.vdocuments.us/reader034/viewer/2022042814/5558bd86d8b42aa52a8b5042/html5/thumbnails/47.jpg)
AMD Singleton Module
define('foobar', function () { return { init: function (prefix) { this.prefix = prefix; } echo: function (input) { return this.prefix + input; } };});
![Page 48: this](https://reader034.vdocuments.us/reader034/viewer/2022042814/5558bd86d8b42aa52a8b5042/html5/thumbnails/48.jpg)
Cons
• Function can be borrowed
• Not doing on right `this` you expect
![Page 49: this](https://reader034.vdocuments.us/reader034/viewer/2022042814/5558bd86d8b42aa52a8b5042/html5/thumbnails/49.jpg)
Avoid Use this
define('foobar', function () { var self = {}; return { init: function (prefix) { self.prefix = prefix; } echo: function (input) { return self.prefix + input; } };});
![Page 50: this](https://reader034.vdocuments.us/reader034/viewer/2022042814/5558bd86d8b42aa52a8b5042/html5/thumbnails/50.jpg)
Constructors?
• Use bind to protect methods if necessary
![Page 51: this](https://reader034.vdocuments.us/reader034/viewer/2022042814/5558bd86d8b42aa52a8b5042/html5/thumbnails/51.jpg)
Constructor Without this
function Person(birth, gender) { var person = { birth: (birth || '1970/01/01'), gender: (gender || 'M') }; return { getBirth: function () { return person.birth; }, getGender: function () { return person.gender; } };}
![Page 52: this](https://reader034.vdocuments.us/reader034/viewer/2022042814/5558bd86d8b42aa52a8b5042/html5/thumbnails/52.jpg)
to new or not to new
var 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"
![Page 53: this](https://reader034.vdocuments.us/reader034/viewer/2022042814/5558bd86d8b42aa52a8b5042/html5/thumbnails/53.jpg)
Cons
• No prototype inheritance
• More memory usage for methods
![Page 54: this](https://reader034.vdocuments.us/reader034/viewer/2022042814/5558bd86d8b42aa52a8b5042/html5/thumbnails/54.jpg)
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') }; } );});
![Page 55: this](https://reader034.vdocuments.us/reader034/viewer/2022042814/5558bd86d8b42aa52a8b5042/html5/thumbnails/55.jpg)
Who Use this Tip
• jQuery.Deferred
• jQuery.Callbacks
![Page 56: this](https://reader034.vdocuments.us/reader034/viewer/2022042814/5558bd86d8b42aa52a8b5042/html5/thumbnails/56.jpg)
Deferred Chaining
var firstDfd = $.Deferred(), secondDfd = $.Deferred(), thirdDfd = $.Deferred(); firstDfd.done(secondDfd.resolve);secondDfd.done(thirdDfd.resolve);
firstDfd.resolve(); // All Deferred object resolved here
![Page 57: this](https://reader034.vdocuments.us/reader034/viewer/2022042814/5558bd86d8b42aa52a8b5042/html5/thumbnails/57.jpg)
Callbacks
https://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;
![Page 58: this](https://reader034.vdocuments.us/reader034/viewer/2022042814/5558bd86d8b42aa52a8b5042/html5/thumbnails/58.jpg)
Callbacks
https://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;
![Page 59: this](https://reader034.vdocuments.us/reader034/viewer/2022042814/5558bd86d8b42aa52a8b5042/html5/thumbnails/59.jpg)
Actually Are
promise['done'] = resolveCallbacks.add;promise['fail'] = rejectCallbacks.add;promise['progress'] = notifyCallbacks.add;
// skip...
deferred["resolveWith"] = resolveCallbacks.fireWith;deferred["rejectWith"] = rejectCallbacks.fireWith;deferred["notifyWith"] = notifyCallbacks.fireWith;
![Page 60: this](https://reader034.vdocuments.us/reader034/viewer/2022042814/5558bd86d8b42aa52a8b5042/html5/thumbnails/60.jpg)
Summary
• Understand `this`
• Understand how not to use `this`
• Use `this` carefully if necessary
![Page 61: this](https://reader034.vdocuments.us/reader034/viewer/2022042814/5558bd86d8b42aa52a8b5042/html5/thumbnails/61.jpg)
Trade-Off
• ‘Not use this’ requires more memory on methods definition and not easy to inheritance object
• Benefit is you can write more clear, simple code
![Page 62: this](https://reader034.vdocuments.us/reader034/viewer/2022042814/5558bd86d8b42aa52a8b5042/html5/thumbnails/62.jpg)
References
![Page 63: this](https://reader034.vdocuments.us/reader034/viewer/2022042814/5558bd86d8b42aa52a8b5042/html5/thumbnails/63.jpg)
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/this
![Page 64: this](https://reader034.vdocuments.us/reader034/viewer/2022042814/5558bd86d8b42aa52a8b5042/html5/thumbnails/64.jpg)
Questions?
http://www.flickr.com/photos/roman/5610736/