Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Comparing changes

Choose two branches to see what's changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base fork: creationix/proto
base: v0.0.1
...
head fork: creationix/proto
compare: master
Checking mergeability… Don't worry, you can still create the pull request.
  • 8 commits
  • 3 files changed
  • 0 commit comments
  • 1 contributor
Commits on Jul 12, 2010
@creationix Wrap object literals before calling functions on them. 02a2f46
Commits on Aug 13, 2010
@creationix Remove Object.prototype.mixin and Function.prototype.curry
They are not used that much and I really want to keep
proto minimal.
48fb138
@creationix Name the map and forEach functions. 586e0d1
@creationix Implement a super minimal object library.
This adds Object.prototype.new and Object.prototype.extend.

They make it easy to do prototypal-OO javascript without
ever messing with constructor functions, prototype
properties and "new".
d9b2372
@creationix Update the README. badda73
@creationix Most JS engine, even new ones don't allow functions to be named new. 91821b5
@creationix Add a mini test suite. edf3347
@creationix Fix README 2e783fa
Showing with 110 additions and 48 deletions.
  1. +34 −25 README.markdown
  2. +13 −23 lib/proto.js
  3. +63 −0 test.js
View
59 README.markdown
@@ -1,51 +1,60 @@
# Proto
-This simple js library adds three functions to Object.prototype and one to Function.prototype that are commonly used. Since this only modifies global objects and doesn't export any structures, you don't need the return value when calling `require('proto')`.
+This simple js library adds four functions to Object.prototype. Since this only modifies global objects and doesn't export any structures, you don't need the return value when calling `require('proto')`.
## Object.prototype
All functions added to `Object.prototype` are usable from any object in JavaScript.
-### Object.prototype.forEach
+### Object.prototype.forEach(callback[, thisObject])
This is the most useful of the additions. It allows you to forEach over an `Object` instance's local properties and values just like you can already do with `Array` instances.
require('proto');
- {name: "Tim", age: 28}.forEach(function (value, key) {
- sys.puts(key + " = " + JSON.stringify(value));
+ ({name: "Tim", age: 28}).forEach(function (value, key) {
+ console.log(key + " = " + JSON.stringify(value));
});
-### Object.prototype.map
+### Object.prototype.map(callback[, thisObject])
This works like forEach, except returns an `Array` instance with the returned values of the function calls.
require('proto');
- var pairs = {name: "Tim", age: 28}.map(function (value, key) {
+ var pairs = ({name: "Tim", age: 28}).map(function (value, key) {
return key + " = " + value;
});
// pairs is ["name = Tim", "age = 28"]
-### Object.prototype.mixin
+### Object.prototype.new(args...)
-Does a shallow copy from another object into this one.
+Creates a new version of the current object and calls it's `initialize` function if one exists with the same arguments passed to new.
require('proto');
- GLOBAL.mixin(require('sys'));
- puts("Hello World");
-
-## Function.prototype
-
-Functions added to `Function.prototype` are available to any JavaScript function.
-
-### Function.prototype.curry
-
-Partially applies a function and returns a new function that accepts the remaining arguments.
+ var Rectangle = {
+ initialize: function initialize(width, height) {
+ this.width = width;
+ this.height = height;
+ },
+ get area() {
+ return this.width * this.height;
+ }
+ };
+
+ var rect = Rectangle.new(2, 4);
+ console.log(rect.area);
+
+### Object.prototype.extend(newObject)
+
+Sets the current object as the prototype to the passed in object and returns the new passed in object.
+
+ // Assuming the code from above
+ var Square = Rectangle.extend({
+ initialize: function initialize(side) {
+ this.width = side;
+ this.height = side;
+ }
+ });
+ var square = Square.new(15);
+ console.log(square.area);
- require('proto');
- var fs = require('fs');
- var sys = require('sys');
- // Create a curried version of the readFile function
- var loader = fs.readFile.curry("myfile.txt");
- // Then finish the application of the function
- loader(sys.debug);
View
36 lib/proto.js
@@ -21,13 +21,11 @@ SOFTWARE.
*/
var proto = Object.prototype;
-var func_proto = Function.prototype;
-var arr_proto = Array.prototype;
// Implements a forEach much like the one for Array.prototype.forEach, but for
// any object.
if (typeof proto.forEach !== 'function') {
- Object.defineProperty(proto, "forEach", {value: function (callback, thisObject) {
+ Object.defineProperty(proto, "forEach", {value: function forEach(callback, thisObject) {
var keys = Object.keys(this);
var length = keys.length;
for (var i = 0; i < length; i++) {
@@ -40,7 +38,7 @@ if (typeof proto.forEach !== 'function') {
// Implements a map much like the one for Array.prototype.map, but for any
// object. Returns an array, not a generic object.
if (typeof proto.map !== 'function') {
- Object.defineProperty(proto, "map", {value: function (callback, thisObject) {
+ Object.defineProperty(proto, "map", {value: function map(callback, thisObject) {
var accum = [];
var keys = Object.keys(this);
var length = keys.length;
@@ -52,28 +50,20 @@ if (typeof proto.map !== 'function') {
}});
}
-// Implements a shallow copy onto the current object.
-if (typeof proto.mixin !== 'function') {
- Object.defineProperty(proto, "mixin", {value: function (obj) {
- var keys = Object.keys(obj);
- var length = keys.length;
- for (var i = 0; i < length; i++) {
- var key = keys[i];
- this[key] = obj[key];
- }
- return this;
+// Implement extend for easy prototypal inheritance
+if (typeof proto.extend !== 'function') {
+ Object.defineProperty(proto, "extend", {value: function extend(obj) {
+ obj.__proto__ = this;
+ return obj;
}});
}
-// Implements a function curry function. This allows you to call part of a
-// function later.
-if (typeof func_proto.curry !== 'function') {
- Object.defineProperty(func_proto, "curry", {value: function () {
- var fn = this;
- var first = arr_proto.slice.call(arguments);
- return function () {
- return fn.apply(this, first.concat(arr_proto.slice.call(arguments)));
- };
+// Implement new for easy self-initializing objects
+if (typeof proto.new !== 'function') {
+ Object.defineProperty(proto, "new", {value: function () {
+ var obj = Object.create(this);
+ if (obj.initialize) obj.initialize.apply(obj, arguments);
+ return obj;
}});
}
View
63 test.js
@@ -0,0 +1,63 @@
+var assert = require('assert');
+
+// A mini expectations module to ensure expected callback fire at all.
+var expectations = {};
+function expect(message) {
+ expectations[message] = new Error("Missing expectation: " + message);
+}
+function fulfill(message) {
+ delete expectations[message];
+}
+process.addListener('exit', function () {
+ Object.keys(expectations).forEach(function (message) {
+ throw expectations[message];
+ });
+});
+
+require('./lib/proto');
+
+
+var Rectangle = {
+ initialize: function initialize(width, height) {
+ this.width = width;
+ this.height = height;
+ },
+ get area() {
+ return this.width * this.height;
+ }
+};
+
+var Square = Rectangle.extend({
+ initialize: function initialize(side) {
+ this.width = side;
+ this.height = side;
+ }
+});
+
+var rect = Rectangle.new(2, 5);
+var square = Square.new(3);
+var data = {name: "Tim Caswell", age: 28};
+var self = {};
+
+assert.equal(rect.area, 10, "Rectangle should have area of 10");
+assert.equal(square.area, 9, "Square should have area of 9");
+assert.ok(Rectangle.isPrototypeOf(Square), "Square inherits from Rectangle");
+assert.ok(Rectangle.isPrototypeOf(rect), "instances of Rectangle inherit from it");
+assert.ok(Square.isPrototypeOf(square), "instances of Square inherit from it");
+assert.ok(Rectangle.isPrototypeOf(square), "instances of Square inherit from Rectangle");
+expect('forEach');
+data.forEach(function (value, key, obj) {
+ fulfill('forEach');
+ assert.equal(value, data[key], "Value should match");
+ assert.equal(obj, data, "Third arguments should be original object")
+ assert.equal(this, self, "this should be same as set in forEach")
+}, self);
+expect('map');
+var result = data.map(function (value, key, obj) {
+ fulfill('map');
+ assert.equal(value, data[key], "Value should match");
+ assert.equal(obj, data, "Third arguments should be original object")
+ assert.equal(this, self, "this should be same as set in forEach");
+ return [key, value];
+}, self);
+assert.deepEqual(result, [ [ 'name', 'Tim Caswell' ], [ 'age', 28 ] ], "Map should work as expected");

No commit comments for this range

Something went wrong with that request. Please try again.