You can subclass native object, the most often sub-classed object is the Object class itself.
Let's first see some cases that you do with sub-classing the object class.
Object.prototype.keys1 = function () { var keys1 = []; for (var i in this) { keys1.push(i); } return keys1; };
However, the gotchas above is that when you call keys1(), it may returns more properties than youmight expect it to returns. let's see the example below.
var obj = { a: 1, b: 2, c: 3 }; assert(obj.keys1().length != 3, "The 3 existing properties plus the new keys method keys1, and others");
so you might take care of which properties are on the actual object rather than on inherited prototyped object.
Below is the improved version.
Object.prototype.keys = function () { var keys = []; for (var i in this) { if (this.hasOwnProperty(i)) { keys.push(i); } } return keys; };
And below is the test code
var obj = { a: 1, b: 2, c: 3 }; assert(obj.keys().length == 3, "Only the 3 exiting properties are included.");
Extending the Array.
due to some reason, the IE does not support directly sub-classing the Array, because the property of length of Array is immutable. but you can take the following workaround.
/** * @MyArray now fake the interface of Array, but it does not inherit from Array directly now. */ function MyArray() { } // this length property is to simulate the Array length property, of which is essential to simulate native array object MyArray.prototype.length = 0; (function () { var methods = ['push', 'pop', 'shift', 'unshift', 'slice', 'splice', 'join']; for (var i = 0; i < methods.length; i++) { (function(name) { MyArray.prototype[name] = function() { return Array.prototype[name].apply(this, arguments); }; })(methods[i]); } })();
and then you can do the test via the following code.
var mine = new MyArray(); mine.push(1, 2, 3); assert(mine.length == 3, "All the items are on our sub-classed array."); assert(!(mine instanceof Array), "We are sub-classing array, though");
Extending numbers
You might think you can override the number class so that you can add extra functions to the function literal; However, this is not always true, because of the way how the Javascript engine parse numbers and its properties of the number, it might not work as you expected, as illustrated in the following example.
Number.prototype.add = new function (num) { return this + num; }
and the following code shows the tests and its results.
var n = 5; assert(n.add(3) == 8, "It works fine if the number is an varaible."); alert((5).add(3) == 8, " Also works if a number is wrapping in parenthesis.");
Following is the full code.
/************************************** *@Summary * This shows how you can subclass some native object from javascript * * this utilize this feature to extend the element in the HTML * * @Usage: * * @TODO: * test it ***************************************/ /** * First attempt to subclass the native Array object * * @Comment: there are some restriction by the IE explorer in that it simply does not allow the Array type to be inherted, the reason is becaue the length property is immutable */ //function MyArray() { } //MyArray.prototype = new Array(); //var mine = new MyArray(); //mine.push(1, 2, 3); //assert(mine.length == 3, "All the items are on our sub-classed array."); //assert(mine instanceof Array, "Verify that we implement Array functionality."); Object.prototype.keys1 = function () { var keys1 = []; for (var i in this) { keys1.push(i); } return keys1; }; Object.prototype.keys = function () { var keys = []; for (var i in this) { if (this.hasOwnProperty(i)) { keys.push(i); } } return keys; }; /** * @MyArray now fake the interface of Array, but it does not inherit from Array directly now. */ function MyArray() { } // this length property is to simulate the Array length property, of which is essential to simulate native array object MyArray.prototype.length = 0; (function () { var methods = ['push', 'pop', 'shift', 'unshift', 'slice', 'splice', 'join']; for (var i = 0; i < methods.length; i++) { (function(name) { MyArray.prototype[name] = function() { return Array.prototype[name].apply(this, arguments); }; })(methods[i]); } })(); Number.prototype.add = new function (num) { return this + num; }
and its harnessed test.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title></title> <script type="text/javascript" src="../unit.js"></script> <script type="text/javascript" src="subclassnative.js"></script> <script type="text/javascript"> var mine = new MyArray(); mine.push(1, 2, 3); window.onload = function () { test("subclass native methods test", function () { var mine = new MyArray(); mine.push(1, 2, 3); assert(mine.length == 3, "All the items are on our sub-classed array."); assert(!(mine instanceof Array), "We are sub-classing array, though"); }); test("subclass native method test2", function () { var obj = { a: 1, b: 2, c: 3 }; assert(obj.keys1().length == 5, "The 3 existing properties plus the new keys method keys1, and keys"); assert(obj.keys().length == 3, "Only the 3 exiting properties are included."); // does not work, cause syntax error // assert(5.add(3) == 8, "Doesnot work, cause syntax error."); var n = 5; assert(n.add(3) == 8, "It works fine if the number is an varaible."); alert((5).add(3) == 8, " Also works if a number is wrapping in parenthesis."); } ); } </script> <style type="text/css" > #results li.pass { color: Green } #results li.fail { color: Red } </style> </head> <body> <ul id="results" /> </body> </html>