0
LEARNING FROM LIBRARIES
|Trevor Landau @trevor_landau
ABOUT
WHAT LIBS?
WHAT DID I MAKE?
function Collection() {}
JQUERY
NOCONFLICT
window.Collection = 'foo';
var oldC = window.Collection;
Collection.noConflict = function () {
window.Collectio...
LENGTH
Collection.prototype = {
length: 0
};
var c = new Collection;
Array.prototype.push.call(c, 1, 2);
log(c.length); //...
CONSTRUCTOR FACADE
function Collection(args) {
if (args && !Array.isArray(args) && arguments.length >= 0) {
if (typeof arg...
BACKBONE
ALL ARRAY BELONG TO US
function Collection(args) {
this.push.apply(this, args);
}
var omit = ['length', 'constructor', 'to...
ON && TRIGGER
c.on('push', function () {
log('push event', arguments); // 4, 5, 6
});
c.push(4, 5, 6);
ON
on: function (name, fn, ctx) {
this._events = this._events || {};
var events = this._events[name] || (this._events[name...
TRIGGER
trigger: function (name) {
if (!this._events) return this;
var args = __slice.call(arguments, 1);
var events = thi...
LETS SEE IN OUR API
Object.getOwnPropertyNames(arrProto).forEach(function (fn) {
if (omit.indexOf(fn) > -1) return;
Collec...
TOJSON
Collection.prototype.toJSON = function () {
return this.map(function (val) {
return val;
});
};
var c = new Collect...
UNDERSCORE
Collection.zip = function () {
var args = __slice.call(arguments);
var lengths = args.map(function (c) { return...
ANGULAR
http://jsperf.com/apply-vs-call-vs-invoke
// performant apply
var pApply = function (args, fn, ctx) {
switch (args...
LET'S SEE IT IN THE API
function Collection(args) {
// Accept different types
args = this._toArray(args) || [];
pApply(arg...
MOCHA
Collection.prototype.repr = function () {
var self = this;
// override toJSON for repr purposes
this.toJSON = null;
...
SHOULD.JS
GET
Collection.prototype = {
get size() {
return this.length;
},
get json() {
return JSON.stringify(this);
}
};
DEFINEPROPERTY
var omit = ['length', 'constructor', 'toString', 'toLocalString'];
Object.getOwnPropertyNames(arrProto).for...
THE END
https://github.com/landau/learningfromlibraries
Upcoming SlideShare
Loading in...5
×

Learning from JavaScript Libraries by Trevor Landau

415

Published on

jQuery runs on approximately 50% of all websites and is the de facto standard for DOM manipulation. Most front end developers use it, but how well do they understand what's happening when they use the API? How does a library take on the problems it solves? What are the reasons behind some of the techniques it uses? Observing the code under the hood of a library/framework is a fantastic way to become a better developer and thereby user of that library/framework. Better understanding of design patterns in some of the most popular libraries can open opportunities to contribute and be a better open source citizen.

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

  • Be the first to like this

No Downloads
Views
Total Views
415
On Slideshare
0
From Embeds
0
Number of Embeds
9
Actions
Shares
0
Downloads
1
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Transcript of "Learning from JavaScript Libraries by Trevor Landau"

  1. 1. LEARNING FROM LIBRARIES |Trevor Landau @trevor_landau
  2. 2. ABOUT
  3. 3. WHAT LIBS?
  4. 4. WHAT DID I MAKE? function Collection() {}
  5. 5. JQUERY
  6. 6. NOCONFLICT window.Collection = 'foo'; var oldC = window.Collection; Collection.noConflict = function () { window.Collection = oldC; return Collection; }; var C = Collection.noConflict(); log(typeof C, typeof Collection); // object, string
  7. 7. LENGTH Collection.prototype = { length: 0 }; var c = new Collection; Array.prototype.push.call(c, 1, 2); log(c.length); // 2
  8. 8. CONSTRUCTOR FACADE function Collection(args) { if (args && !Array.isArray(args) && arguments.length >= 0) { if (typeof args.toArray === 'function') { args = args.toArray(); } else { args = __slice.apply(arguments); } } else { args = []; } if (args.length) Array.prototype.push.apply(this, args); } var c = new Collection([1,2,3]); var c2 = new Collection(1,2,3); var c3 = new Collection({ toArray: function () { return [1,2,3]; } }); log(c.length, c2.length, c3.length); // 3, 3, 3
  9. 9. BACKBONE
  10. 10. ALL ARRAY BELONG TO US function Collection(args) { this.push.apply(this, args); } var omit = ['length', 'constructor', 'toString', 'toLocalString']; Object.getOwnPropertyNames(arrProto).forEach(function (fn) { if (omit.indexOf(fn) > -1) return; Collection.prototype[fn] = function () { var args = __slice.call(arguments); return arrProto[fn].apply(this, args); }; }); var c = new Collection([1,2,3]); log(c.length); // 3 log(c.unshift(0)); // [0, 1, 2, 3]
  11. 11. ON && TRIGGER c.on('push', function () { log('push event', arguments); // 4, 5, 6 }); c.push(4, 5, 6);
  12. 12. ON on: function (name, fn, ctx) { this._events = this._events || {}; var events = this._events[name] || (this._events[name] = []); events.push({ fn: fn, ctx: ctx || this }); return this; }
  13. 13. TRIGGER trigger: function (name) { if (!this._events) return this; var args = __slice.call(arguments, 1); var events = this._events[name]; if (events) { events.forEach(function (ev) { ev.fn.apply(ev.ctx, args); }); } return this; }
  14. 14. LETS SEE IN OUR API Object.getOwnPropertyNames(arrProto).forEach(function (fn) { if (omit.indexOf(fn) > -1) return; Collection.prototype[fn] = function () { var args = __slice.call(arguments); var ret = arrProto[fn].apply(this, args); this.trigger(fn, ret); return ret; }; });
  15. 15. TOJSON Collection.prototype.toJSON = function () { return this.map(function (val) { return val; }); }; var c = new Collection(1,2,3); // Without method JSON.stringify(c); // '{"0":1,"1":2,"2":3}' - will also contain other props... // With method JSON.stringify(c); // '[1,2,3]'
  16. 16. UNDERSCORE Collection.zip = function () { var args = __slice.call(arguments); var lengths = args.map(function (c) { return c.length; }); var length = Math.max.apply(Math, lengths); var results = new Array(length); var map = function (c) { return c[i]; }; for (var i = 0; i < length; i += 1) { results[i] = args.map(map); } return results; } var c = new Collection([1,2]); var c2 = new Collection([3,4]); console.log(Collection.zip(c, c2)); // [[1,3],[2,4]];
  17. 17. ANGULAR http://jsperf.com/apply-vs-call-vs-invoke // performant apply var pApply = function (args, fn, ctx) { switch (args.length) { case 0: return ctx[fn](); case 1: return ctx[fn](args[0]); case 2: return ctx[fn](args[0], args[1]); case 3: return ctx[fn](args[0], args[1], args[2]); case 4: return ctx[fn](args[0], args[1], args[2], args[3]); case 5: return ctx[fn](args[0], args[1], args[2], args[3], args[4]); ... case 10: return ctx[fn](args[0], args[1], args[2], args[3], args[4], args[5 default: return ctx[fn].apply(ctx, args); } };
  18. 18. LET'S SEE IT IN THE API function Collection(args) { // Accept different types args = this._toArray(args) || []; pApply(args, 'push', this); }
  19. 19. MOCHA Collection.prototype.repr = function () { var self = this; // override toJSON for repr purposes this.toJSON = null; var repr = JSON.stringify(this, function (key, val) { if (self === val || !isNaN(parseInt(key, 10))) { return val; } return void 0; }); // reset delete this.toJSON; return repr; }
  20. 20. SHOULD.JS
  21. 21. GET Collection.prototype = { get size() { return this.length; }, get json() { return JSON.stringify(this); } };
  22. 22. DEFINEPROPERTY var omit = ['length', 'constructor', 'toString', 'toLocalString']; Object.getOwnPropertyNames(arrProto).forEach(function (fn) { if (omit.indexOf(fn) > -1) return; Object.defineProperty(Collection.prototype, fn, { value: function () { var args = __slice.call(arguments); var ret = arrProto[fn].apply(this, args); var evArgs = [fn, ret]; pApply(evArgs, 'trigger', this); return ret; } }); });
  23. 23. THE END https://github.com/landau/learningfromlibraries
  1. A particular slide catching your eye?

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

×