Closure Library用goog.provide()和goog.require()两个方法来建立其中的依赖关系.
// Calling this function:
goog.provide('example.of.a.long.namespace');
// Is equivalent to doing:
//
// var example = goog.global.example || (goog.global.example = {});
// if (!example.of) example.of = {};
// if (!example.of.a) example.of.a = {};
// if (!example.of.a.namespace) example.of.a.namespace = {};
// Because goog.provide() has been called, it is safe to assume that
// example.of.a.long.namespace refers to an object, so it is safe to
// add new properties to it without checking for null.
example.of.a.long.namespace.isOver = function() { alert('easy, eh?'); };
// Creates a namespace named "goog".
var goog = {};
// Creates a new namespace named "goog.array".
goog.array = {};
// Adds a function named binarySearch to the "goog.array" namespace.
goog.array.binarySearch = function(arr, target, opt_compareFn) { /*...*/ };
// Adds a function named sort to the "goog.array" namespace.
goog.array.sort = function(arr, opt_compareFn) { /*...*/ };
goog.provide('example.radius');
/**
* @param {number} radius
* @param {goog.math.Coordinate} point
* @return {boolean} whether point is within the specified radius
*/
example.radius.isWithinRadius = function(radius, point) {
return Math.sqrt(point.x * point.x + point.y * point.y) <= radius;
};
goog.provide('example.radius');
goog.require('goog.math.Coordinate');
/**
* @param {number} radius
* @param {goog.math.Coordinate} point
* @return {boolean} whether point is within the specified radius
*/<pre name="code" class="javascript">example.radius.isWithinRadius = function(radius, point) {
var origin = new goog.math.Coordinate(0, 0);
var distance = goog.math.Coordinate.distance(point, origin);<span style="font-family: Arial, Helvetica, sans-serif;">return distance <= radius;</span><span style="font-family: Arial, Helvetica, sans-serif;">};</span>
</pre><br /></div><h3><span style="white-space:pre"> </span><em>goog.addDependency(relativePath,provides,requires)</em></h3><div><span style="font-style: italic; white-space: pre;"> </span>goog.addDependency()被用来创建和管理未编译JavaScript文件中的依赖图,当JavaScript被编译后,编译期goog.provide()和goog.require()会被检查以确保确保没有命名空间在被provide之前就require的,如果检查顺利通过,goog.provide()将会被对象替换掉,goog.require也会完全去除.编译后,就没有必要在client端构建依赖图了,所以当COMPILED为true的时候,goog.addDependency()和它所依赖的全局常量都会被去除.</div><div><span style="white-space:pre"> </span>然而,未编译的Closure代码依赖于goog.addDependency(),它决定了哪些额外的JavaScript文件需要被加载.看下边的例子,example.View命名空间依赖于example.Model命名空间:</div><div><pre name="code" class="javascript">// File: model.js
goog.provide('example.Model');
example.Model.getUserForEmailAddress = function(emailAddress) {
if (emailAddress == 'bolinfest@gmail.com') {
return { firstName: 'Michael', lastName: 'Bolin' };
}
};
// File: view.js
goog.provide('example.View');
goog.require('example.Model');
example.View.displayUserInfo = function(emailAddress) {
var user = example.Model.getUserForEmailAddress(emailAddress);
document.write('First Name: ' + user.firstName);
// etc.
};
// This file was autogenerated by calcdeps.py
goog.addDependency("../../primitives/model.js", ['example.Model'], []);
goog.addDependency("../../primitives/view.js", ['example.View'], ['example.Model']);
<!doctype html>
<html>
<head></head>
<body>
<script src="../closure-library-r155/goog/base.js"></script>
<!--
When base.js is loaded, it will call:
document.write('<script src="../closure-library-r155/goog/deps.js"></script>');
The deps.js file contains all of the calls to goog.addDependency() to build
the dependency graph for the Closure Library. The deps.js file will be
loaded after the base.js script tag but before any subsequent script tags.
-->
<!--
This loads the two calls to goog.addDependency() for example.Model and
example.View.
-->
<script src="model-view-deps.js"></script>
<script>
// When this script block is evaluated, model-view-deps.js will already have
// been loaded. Using the dependency graph built up by goog.addDependency(),
// goog.require() determines that example.View is defined in
// ../../primitives/view.js, and that its dependency, example.Model, is
// defined in ../../primitives/model.js. These paths are relative to base.js,
// so it will call the following to load those two files:
//
// document.write('<script ' +
// 'src="../closure-library-r155/goog/../../primitives/model.js"><\/script>');
// document.write('<script ' +
// 'src="../closure-library-r155/goog/../../primitives/view.js"><\/script>');
//
// Like deps.js, model.js and view.js will not be loaded until this script
// tag is fully evaluated, but they will be loaded before any subsequent
// script tags.
goog.require('example.View'); // calls document.write() twice
// The example.View namespace cannot be used here because view.js has not
// been loaded yet, but functions that refer to it may be defined:
var main = function() {
example.View.displayUserInfo('bolinfest@gmail.com');
};
// So long as view.js is loaded before this function is executed, this is not
// an issue because example.View.displayUserInfo() is not evaluated
// until main() is called. The following, however, would be evaluated
// immediately:
alert(typeof example); // alerts 'undefined'
</script>
<script>
// Both model.js and view.js will be loaded before this <script> tag,
// so example.Model and example.View can be used here.
alert(typeof example); // alerts 'object'
main(); // calls function that uses example.View
</script>
</body>
</html>
var a = function() {
alert('Hello world!');
};
var b = goog.partial(alert, 'Hello world!');
// Recall that Math.max() is a function that takes an arbitrary number of
// arguments and returns the greatest value among the arguments given.
// If no arguments are passed, then it returns -Infinity.
var atLeastTen = goog.partial(Math.max, 10);
atLeastTen(-42, 0, 7); // returns 10: equivalent to Math.max(10, -42, 0, 7);
atLeastTen(99); // returns 99: equivalent to Math.max(10, 99);
atLeastTen(); // returns 10: equivalent to Math.max(10);
var createDeferredAlertFunction = function() {
// Note the XMLHttpRequest constructor is not available in Internet Explorer 6.
var xhr = new XMLHttpRequest();
return function() {
alert('Hello world!');
};
};
var deferredAlertFunction = createDeferredAlertFunction();
ProgressBar.prototype.update = function(statusBar) {
if (!this.isComplete()) {
var percentComplete = this.getPercentComplete();
statusBar.repaintStatus(percentComplete);
// Update the statusBar again in 500 milliseconds.
var updateAgain = function() { this.update(statusBar); };
setTimeout(updateAgain, 500);
}
};
ProgressBar.prototype.update = function(statusBar) {
if (!this.isComplete()) {
var percentComplete = this.getPercentComplete();
statusBar.repaintStatus(percentComplete);
// Update the statusBar again in 500 milliseconds.
var self = this;
var updateAgain = function() { self.update(statusBar); };
setTimeout(updateAgain, 500);
}
};
ProgressBar.prototype.update = function(statusBar) {
if (!this.isComplete()) {
var percentComplete = this.getPercentComplete();
statusBar.repaintStatus(percentComplete);
// Update the statusBar again in 500 milliseconds.
var updateAgainWithGoogBind = goog.bind(this.update, this, statusBar);
setTimeout(updateAgainWithGoogBind, 500);
}
};
var GMap2 = goog.getObjectByName('google.maps.GMap2');
var map = new GMap2(document.body);
// window.location will not be defined if the code is executed in Rhino
var href = goog.getObjectByName('window.location.href');
var href = (window && window.location && window.location.href) || null;
var workerPool = goog.getObjectByName('google.gears.workerPool');
goog.provide('Lottery');
Lottery.doDrawing = function() {
Lottery.winningNumber = Math.round(Math.random() * 1000);
};
// In uncompiled mode, this is redundant.
goog.exportProperty(Lottery, 'doDrawing', Lottery.doDrawing);
现在以编译后代码为例:
var a = {}; // Lottery namespace
a.a = function() { /* ... */ }; // doDrawing has been renamed to 'a'
a.doDrawing = a.a; // doDrawing exported on Lottery
Lottery.winningNumber = 747;
goog.exportProperty(Lottery, 'winningNumber', Lottery.winningNumber);
Lottery.getWinningNumber = function() { return Lottery.winningNumber; };
goog.exportProperty(Lottery, 'getWinningNumber', Lottery.getWinningNumber);
var a = {};
a.b = function() { a.a = Math.round(Math.random() * 1000); };
a.doDrawing = a.b;
a.a = 747;
a.winningNumber = a.a;
a.c = function() { return a.a; };
a.getWinningNumber = a.c;
var hijackLottery = function(myNumber) {
Lottery.doDrawing();
Lottery.winningNumber = myNumber;
return Lottery.getWinningNumber();
};
Lottery.setWinningNumber = function(myNumber) {
Lottery.winningNumber = myNumber;
};
goog.exportProperty(Lottery, 'setWinningNumber', Lottery.setWinningNumber);
var hijackLottery = function(myNumber) {
Lottery.doDrawing();
Lottery.setWinningNumber(myNumber);
return Lottery.getWinningNumber();
};
Lottery.MAX_TICKET_NUMBER = 999;
goog.exportProperty(Lottery, 'MAX_TICKET_NUMBER', Lottery.MAX_TICKET_NUMBER);
Lottery.doDrawingFunction_ = function() {};
Lottery.setDoDrawingFunction = function(f) {
Lottery.doDrawingFunction_ = f;
};
goog.exportProperty(Lottery, 'setDoDrawingFunction',
Lottery.setDoDrawingFunction);
Lottery.doDrawing = function() {
Lottery.doDrawingFunction_.apply(null, arguments);
};
goog.exportProperty(Lottery, 'doDrawing', Lottery.doDrawing);
goog.exportSymbol('Lottery.doDrawing', Lottery.doDrawing);
goog.exportSymbol('Lottery.getWinningNumber', Lottery.getWinningNumber);
goog.exportSymbol('Lottery.setWinningNumber', Lottery.setWinningNumber);
goog.exportSymbol('Lottery.MAX_TICKET_NUMBER', Lottery.MAX_TICKET_NUMBER);