運用Closure Compiler 打造高品質的JavaScript

48
運用Closure Compiler 打造高品質的JavaScript Hedger 王璽

description

運用Closure Compiler 打造高品質的JavaScript Hedger 王璽

Transcript of 運用Closure Compiler 打造高品質的JavaScript

Page 1: 運用Closure Compiler 打造高品質的JavaScript

運用Closure Compiler打造高品質的JavaScript

Hedger 王璽

Page 2: 運用Closure Compiler 打造高品質的JavaScript

前端工程師Yahoo! 2004 - 2008

Google 2008 - Present

Page 3: 運用Closure Compiler 打造高品質的JavaScript

適用場合Complex JS Application

Object-Oriented JavaScript

Page 4: 運用Closure Compiler 打造高品質的JavaScript

面向對象的 JavaScript

Page 5: 運用Closure Compiler 打造高品質的JavaScript

困境

Page 6: 運用Closure Compiler 打造高品質的JavaScript

缺乏類別 Class

Page 7: 運用Closure Compiler 打造高品質的JavaScript

// John Resig's Approach.function User(name){ if ( !(this instanceof User) ) return new User(name); this.name = name;}

var userA = new User('John'); // An instance.var userB = User('Jane'); // Also an instance.

Page 8: 運用Closure Compiler 打造高品質的JavaScript

缺乏私有 @private

Page 9: 運用Closure Compiler 打造高品質的JavaScript

// Crockford's approach.function User(name) { var _name = name;

// Getter for the private name. this.getName = function() { return _name; };}

Page 10: 運用Closure Compiler 打造高品質的JavaScript

缺乏包 Package

Page 11: 運用Closure Compiler 打造高品質的JavaScript

// Global is evil.var myProjectDemoUserName = 'foo';

// Meeh...my.project.demo.user.Name = 'foo';

Page 12: 運用Closure Compiler 打造高品質的JavaScript

缺乏伸縮性 scalability

Page 13: 運用Closure Compiler 打造高品質的JavaScript

jQueryMooToolprototype

script.aculo.usYUI

ExtJSDojo

Closure

Page 14: 運用Closure Compiler 打造高品質的JavaScript

var p1 = new Person('John');var p2 = new Person('Jane');var people = new People();people.add(p1);people.add(p2);document.write(people.getCount());

Functional or OO?

Page 15: 運用Closure Compiler 打造高品質的JavaScript

<script src="http://yui.yahooapis.com/2.8.2r1/build/dom/dom-min.js"></script>

// YAHOO.util.DragDropMgr

/** * Returns the specified element style property * @method getStyle * @param {HTMLElement} el the element * @param {string} styleProp the style property * @return {string} The value of the style property * @deprecated use YAHOO.util.Dom.getStyle * @static */getStyle: function(el, styleProp) { return YAHOO.util.Dom.getStyle(el, styleProp);},

Page 16: 運用Closure Compiler 打造高品質的JavaScript

人人都是JavaScript

忍者

Page 17: 運用Closure Compiler 打造高品質的JavaScript

if (!('a' in window)) { var a = 1;}alert(a);

Page 18: 運用Closure Compiler 打造高品質的JavaScript

Closure Compiler

Page 19: 運用Closure Compiler 打造高品質的JavaScript

It is a true compiler for JavaScript. Instead of compiling from a source language to machine code, it compiles from JavaScript to better JavaScript. It parses your JavaScript, analyzes it, removes dead code and rewrites and minimizes what’s left. It also checks syntax, variable references, and types, and warns about common JavaScript pitfalls.

Page 20: 運用Closure Compiler 打造高品質的JavaScript

@constructor

Page 21: 運用Closure Compiler 打造高品質的JavaScript

/** * @constructor */function MyClass() {}

// Pass.var obj1 = new MyClass();

// ERROR: Constructor function (this:MyClass):// class should be called with the "new" keyword.var obj2 = MyClass(); // Error.

Page 22: 運用Closure Compiler 打造高品質的JavaScript

@private

Page 23: 運用Closure Compiler 打造高品質的JavaScript

// File demo1.js

/** * A User. * @constructor */function User() {

/** * The creation date. * @private * @type {Date} */ this._birthDay = new Date();}

/** * @return {number} The creation year. */User.prototype.getBirthYear = function() { return this._birthDay.getYear();};

// File demo2.js

// Create a user.var me = new User();

// Print out its birth year.document.write(me. getBirthYear().toString());

// Errordocument.write(me. _birthDay.toString());

Page 24: 運用Closure Compiler 打造高品質的JavaScript

@extend

Page 25: 運用Closure Compiler 打造高品質的JavaScript

/** * The shape * @constructor */function Shape() {}

/** * The Box. * @constructor * @extends {Shape} */function Box()) {}

Page 26: 運用Closure Compiler 打造高品質的JavaScript

@interface@implements

Page 27: 運用Closure Compiler 打造高品質的JavaScript

/** * The shape * @constructor */function Shape() {}

/** @return {number} */Shape.prototype.getSize = function() {};

/** * The Box. * @constructor * @imnplements {Shape} */function Box()) {}/** @inheritDoc */Box.prototype.getSize = function() {return 0;};

Page 28: 運用Closure Compiler 打造高品質的JavaScript

命名空package & namespace

Page 29: 運用Closure Compiler 打造高品質的JavaScript

// Create namespaces.var demo = {};demo.example = {};demo.example.exercise = {};

/** * @constructor */demo.example.exercise.Foo = function() { demo.example.exercise.Foo.print(this.value1); demo.example.exercise.Foo.print(this.value2);};

Page 30: 運用Closure Compiler 打造高品質的JavaScript

STRICT type checking 嚴格的類型檢查

Page 31: 運用Closure Compiler 打造高品質的JavaScript

function User() {}

function UsersGroup() { this.users_ = [];}

UsersGroup.prototype.add = function(user) { // Make sure that only user can be added. if (!(user instanceof User)) { throw new Error('Only user can be added.'); } this.users_.push(user);};

var me = new User();var myGroup = new UsersGroup();myGroup.add(me);

Page 32: 運用Closure Compiler 打造高品質的JavaScript

/** * @constructor */function User() {}

/** * @constructor */function UsersGroup() { /** * @private * @type {Array.<User>} */ this.users_ = [];}

/*** @param {User} user*/UsersGroup.prototype.add = function(user) { this.users_.push(user);};

Page 33: 運用Closure Compiler 打造高品質的JavaScript

@enum

Page 34: 運用Closure Compiler 打造高品質的JavaScript

function Project(status) { this.status_ = status;}

Project.prototype.isBusy = function() { switch (this.status_) { case 'busy':; case 'super_busy': return true; default: return false; }};

var p1 = new Project('busy');var p2 = new Project('super_busy');var p3 = new Project('idle');

document.write(p1.isBusy().toString());document.write(p2.isBusy().toString());document.write(p3.isBusy().toString());

Page 35: 運用Closure Compiler 打造高品質的JavaScript

/** * @constructor * @param {Project.Status} status */function Project(status) { /** * @type {Project.Status} * @private */ this.status_ = status;}

/** * @enum {number} */Project.Status = { BUSY: 0, SUPER_BUSY: 1, IDLE: 2};

/** * @return {boolean} */Project.prototype.isBusy = function() { switch (this.status_) { case Project.Status.BUSY:; case Project.Status.SUPER_BUSY: return true; default: return false; }};

var p1 = new Project(Project.Status.BUSY);var p2 = new Project( Project.Status.SUPER_BUSY);var p3 = new Project(Project.Status.IDLE);

document.write(p1.isBusy().toString());document.write(p2.isBusy().toString());document.write(p3.isBusy().toString());

Page 36: 運用Closure Compiler 打造高品質的JavaScript

@define

Page 37: 運用Closure Compiler 打造高品質的JavaScript

/** * namespace for the Logger. */var Logger = {};

/** * Whether logging should be * enabled. * @define {boolean} */Logger.ENABLED = true;

/** * the log API. * @param {...*} args */Logger.log = function(args) { if (!Logger.ENABLED) { // Don't do anything if logger is disabled. return; } var console = window['console']; if (console) { console['log'].apply(console, arguments); }};

/** * A User. * @param {string} name * @constructor */function LoggerUser(name) { Logger.log('New User', name);}

var me = new LoggerUser('me');

Page 38: 運用Closure Compiler 打造高品質的JavaScript

@casting

Page 39: 運用Closure Compiler 打造高品質的JavaScript

/** * The Model definition. * @constructor */function UserModel() { /** * @type {string} */ this.firstName = '';

/** * @type {string} */ this.lastName = '';}

/** * The User constructor. * @constructor * @param {string} firstName * @param {string} lastName */function User(firstName, lastName) { /** * @type {string} */ this.fullName = firstName + ' ' + lastName;}

/** * A static method that creates a * User from a model. * @param {UserModel} model * @return {User} The user created. */User.createFromUserModel = function(model) { return new User( model.firstName, model.lastName);};

// Cast a simple JSON Object as // {UserModel}.var data = /** @type {UserModel} */({ firstName : 'foo', lastName : 'bar'});

// Create a user from the model.var user = User.createFromUserModel(data);document.write(user.fullName);

Page 40: 運用Closure Compiler 打造高品質的JavaScript

總結

Page 41: 運用Closure Compiler 打造高品質的JavaScript

良好的代碼風格可讀性 / 可維護性 / 可用性Developer, IDE, Compiler, JSDocBuilder

Page 42: 運用Closure Compiler 打造高品質的JavaScript

詳細合理的註釋progressive enhancemen

Page 43: 運用Closure Compiler 打造高品質的JavaScript

良好的開發週期開發/測試/發佈

Page 44: 運用Closure Compiler 打造高品質的JavaScript

保持嚴謹

Page 45: 運用Closure Compiler 打造高品質的JavaScript

展望

Page 46: 運用Closure Compiler 打造高品質的JavaScript

JavaScriptEverywhere

PS3 . iPhone . Android ChromeOS . WebOS

Page 48: 運用Closure Compiler 打造高品質的JavaScript

謝謝大家