Accessing JavaScript in-memory objects - javascript

Is it possible to access JS in-memory objects from within the code? Are there any internal memory inspectors available? Can I list the objects with a given prototype (or type) from code?
// EXAMPLE
function Kitten(name) { this.name = name; }
var kitten = new Kitten('furry');
// ...
// Any features like this?
var kittens = ListObjectsOfType(Kitten);
// Or this?
var kittens2 = ListObjectsWithPrototype(kitten.prototype);
Primarily I'm interested in Google's V8 implementations or ES6 (Harmony) specifications. (I appreciate other technologies too.)

You can create a function for this. Something like:
function ListObjectsOfType(type) {
var result = [];
for( var w in window ) {
var val = window[w];
if( val instanceof type )
result.push(val);
}
return result;
}
If you invoke this from the Chrome Console, you can plainly inspect/collapse the resulting objects.
You can extend it to traverse all window vars (you'll want to skip the defaults though).
I think by definition it is impossible to inspect e.g. the following:
function SomeObj() {
var b = new Kitten('kitty');
}
new SomeObj();
I expect the memory heap to have this obj, but it will not be available/detectable via JS ever.

Related

JavaScript getter and setter

This is such a fundamental question, that I'm sure it's a duplicate, so I apologize in advance, but is this how I write an object such that I use by saying:
myApplication.myFirstMethod(x);
x = myApplication.myFirstMethod();
Here's the code:
myApplication = {};
(function() {
myApplication.myFirstMethod = function() {
var local = {};
if (arguments.length) {
local.result = arguments[0];
}
return local.result;
}
myApplication.mySecondMethod = function() {
var local = {};
if (arguments.length) {
local.result = arguments[0];
}
return local.result;
}
})();
jsFiddle Demo
A more object oriented approach would be to use instantiation and prototype.
Setup
var Application = function(){
this.local = {};
};
Application.prototype.Value = function(){
if (arguments.length) {
this.local.result = arguments[0];
}else{
return this.local.result;
}
};
Used
var app = new Application();
app.Value(6);
alert(app.Value());//6
From a jQuery point of view, they will first screen to see if there are arguments, this code is direct from their source for the val function:
val: function( value ) {
if ( !arguments.length ) {
var elem = this[0];
...
It then goes on to use the element's native API and some other metrics to get the value for the element (In general, the only type of elements which will return a value from val are going to be elements such as input, select, etc. - form elements basically).
At the end of the if block it attempts to return various results based on if it found a value attached to the element (or set of elements). This guarantees that the clause of "setting" never executes when a "get" is encountered. If the case is that "set" is being used it goes through a slightly complex set of code to properly set a value to the element.
The reason that the code shows val: function() is because it is part of an object which is being used to "extend" the jQuery prototype using jQuery's extend functionality.
This is the exact code in a jsfiddle of jQuery's val function
There are many patterns for creating objects like this and everyone has their favorites. Addy Osmani does an excellent job of summarizing the most popular patterns in his Javascript Design Patterns "book". Specifically, this section:
http://addyosmani.com/resources/essentialjsdesignpatterns/book/#designpatternsjavascript
I reread this semi-annualy just to make sure I'm keeping all the patterns in my quiver.

Extending a javascript object

I'm currently working on a platform game engine using javascript and the HTML5 canvas.
I have an object, "platform" which looks something like this...
var platform = function(pid,px,py,pw,ph) {
//Some variables here... and then we have some functions
this.step = function() {
//Update / step events here
}
this.draw = function() {
//Drawing events here
}
//etc.
}
The step() function has all of the calculations for collision detection while the draw() function draws the platform.
What I want to do is make another object called movingPlatform. This will be almost identical to the current platform except for the fact this one moves.
Rather than copying all of the collision detection code I'd like to be able to extend movingPlatform from platform... and then be able to add some additional code into the step() function to the moving platform can... well... move.
Some additional information...
When the game loads, it generates the level using data from a CSV file. I have an array, platforms[] that stores all of the platforms within it.
So to create a platform it looks like this...
platforms.push(new platform(i,data[1],data[2],data[3],data[4]));
I then make the platforms perform their step and draw events during the game's main step and draw events.
i.e.
for(var i=0; i<platforms.length; i++) {
platforms[i].step();
}
Any help would be awesome. Thanks!
I would use the platform class as a "base" object for the moving platform object.
I would do this via the prototype which is JavaScript's implementation of object oriented programming.
More info here How does JavaScript .prototype work?
+ many more articles on the web
You can use Javascript prototype inheritance functionality:
var baseItem = {
push: function(){alert('push');},
pull: function(){alert('pull')}
}
var childItem = {}
childItem.prototype = baseItem;
childItem.push = function(){
//call base function
childItem.prototype.push.call(this);
//do your custom stuff.
alert('I did it again.');
}
childItem.push();
Fiddle
Rather than pure inheritance, here, I'd go with prototype-extension, unless you build some big, ugly factory, just for the sake of saying that "MovingPlatform" inherited from "Platform" in a pure sense, it's not really what you'd expect it to be.
There are a few concerns (cheating, for one), but if your objects are all based wholly around this, and you're okay with people potentially hacking away in the console, then you don't really have much to worry about.
First, understand what you're doing inside of Platform:
var MyObject = function (a) {
this.property = a;
this.method = function (b) { this.property += b; };
};
Every time you make a new MyObject, you're creating a brand new version of the .method function.
That is to say, if you make 10,000 of these, there will be 10,000 copies of that function, as well.
Sometimes that's a very good and safe thing.
It can also be a very slow thing.
The problem is, because everything in your object is using this, and because nothing inside of the function changes, there's no benefit to creating new copies -- just extra memory used.
...so:
MyObject = function (a) {
this.property = a;
};
MyObject.prototype.method = function (b) { this.property += b; };
var o = new MyObject(1);
o.method(2);
o.property; //3
When you call new X, where X has properties/methods on its prototype, those properties/methods get copied onto the object, during its construction.
It would be the same as going:
var method = function (b) { this.property += b; },
o = new MyObject(1);
o.method = method;
o.method(2);
o.property; // 3
Except without the extra work of doing it yourself, by hand.
The benefit here is that each object uses the same function.
They basically hand the function access to their whole this, and the function can do whatever it wants with it.
There's a catch:
var OtherObj = function (a, b) {
var private_property = b,
private_method = function () { return private_property; };
this.public_property = a;
this.unshared_method = function () { var private_value = private_method(); return private_value; };
};
OtherObj.prototype.public_method = function () {
return private_property;
};
var obj = new OtherObj(1, "hidden");
obj.public_property; // 1
obj.unshared_method(); // "hidden"
obj.public_method(); // err -- private_property doesn't exist
So assuming you don't have much you care about staying private, the easiest way of doing this would be to make reusable function, which rely on this, which you then give to multiple prototypes, through extension.
// collision-handling
var testCollision = function (target) { this./*...*/ },
handleCollision = function (obj) { this./* ... */ };
// movement-handling
var movePlatform = function (x, y, elapsed) { this.x += this.speed.x*elapsed; /*...*/ };
// not really the cleanest timestep implementation, but it'll do for examples
var Platform = function (texture, x, y, w, h) {
this.x = x;
// ...
},
MovingPlatform = function (texture, x, y, w, h, speedX, speedY, etc) {
this.etc = etc;//...
};
Platform.prototype.testCollision = testCollision;
Platform.prototype.handleCollision = handleCollision;
MovingPlatform.prototype. // both of the above, plus the movePlatform method
This is a lot by hand.
That's why functions in different libraries will clone or extend objects.
var bunchOfComponents = {
a : function () { },
b : 32,
c : { }
},
myObj = {};
copy(myObj, bunchOfComponents);
myObj.a();
myObj.b; //32
Your function-reuse goes up, while the horror of writing proper Class-based, hierarchical inheritance, with virtual-overrides, abstracts, and shared-private properties, by hand, goes down.
Getting inheritance right in Javascript is somewhat tricky if you're used to class-based languages.
If you're not sharing a lot of behaviours, you might find it easier to just create some shared methods, then make them available to objects of each platform type.
//Create constructors for each type
var Platform = function(pid,px,py,pw,ph) { //By convention, constructors should start with an uppercase character
...
}
var MovingPlatform = function() {
...
}
//Create some reuseable methods
var step = function() {
...
}
var draw = function() {
...
}
var move = function() {
...
}
//Attach your methods to the prototypes for each constructor
Platform.prototype.step = step;
Platform.prototype.draw = draw;
MovingPlatform.prototype.step = step;
MovingPlatform.prototype.draw = draw;
MovingPlatform.prototype.move = move;
...etc
That said, if you do want to build up a proper inheritance chain, there are plenty of articles available to help you: 1 2 3 4

Is there some way to add meta-data to JavaScript objects?

I would like to add key-value pairs of metadata to arbitrary JavaScript objects. This metadata should not affect code that is not aware of the metadata, that means for example
JSON.stringify(obj) === JSON.stringify(obj.WithMetaData('key', 'value'))
MetaData aware code should be able to retrieve the data by key, i.e.
obj.WithMetaData('key', 'value').GetMetaData('key') === 'value'
Is there any way to do it - in node.js? If so, does it work with builtin types such as String and even Number? (Edit Thinking about it, I don't care about real primitives like numbers, but having that for string instances would be nice).
Some Background: What I'm trying to do is cache values that are derived from an object with the object itself, so that
to meta data unaware code, the meta data enriched object will look the same as the original object w/o meta
code that needs the derived values can get it out of the meta-data if already cached
the cache will get garbage collected alongside the object
Another way would be to store a hash table with the caches somewhere, but you'd never know when the object gets garbage collected. Every object instance would have to be taken care of manually, so that the caches don't leak.
(btw clojure has this feature: http://clojure.org/metadata)
You can use ECMA5's new object properties API to store properties on objects that will not show up in enumeration but are nonetheless retrievable.
var myObj = {};
myObj.real_property = 'hello';
Object.defineProperty(myObj, 'meta_property', {value: 'some meta value'});
for (var i in myObj)
alert(i+' = '+myObj[i]); //only one property - #real_property
alert(myObj.meta_property); //"some meta value"
More information here: link
However you're not going to be able to do this on primitive types such as strings or numbers, only on complex types.
[EDIT]
Another approach might be to utilise a data type's prototype to store meta. (Warning, hack ahead). So for strings:
String.prototype.meta = {};
String.prototype.addMeta = function(name, val) { this.meta[name] = val; }
String.prototype.getMeta = function(name) { return this.meta[name]; };
var str = 'some string value';
str.addMeta('meta', 'val');
alert(str.getMeta('meta'));
However this is clearly not ideal. For one thing, if the string was collected or aliased (since simple data types are copied by value, not reference) you would lose this meta. Only the first approach has any mileage in a real-world environment, to be honest.
ES6 spec introduces Map and WeakMap. You can enable these in node by running node --harmony and by enabling the experimental javascript flag in Chrome, (it's also in Firefox by default). Maps and WeakMaps allow objects to be used as keys which can be be used to store metadata about objects that isn't visible to anyone without access to the specific map/weakmap. This is a pattern I now use a lot:
function createStorage(creator){
creator = creator || Object.create.bind(null, null, {});
var map = new Map;
return function storage(o, v){
if (1 in arguments) {
map.set(o, v);
} else {
v = map.get(o);
if (v == null) {
v = creator(o);
map.set(o, v);
}
}
return v;
};
}
Use is simple and powerful:
var _ = createStorage();
_(someObject).meta= 'secret';
_(5).meta = [5];
var five = new Number(5);
_(five).meta = 'five';
console.log(_(someObject).name);
console.log(_(5).meta);
console.log(_(five).meta);
It also facilitates some interesting uses for separating implementation from interface:
var _ = createStorage(function(o){ return new Backing(o) });
function Backing(o){
this.facade = o;
}
Backing.prototype.doesStuff = function(){
return 'real value';
}
function Facade(){
_(this);
}
Facade.prototype.doSomething = function doSomething(){
return _(this).doesStuff();
}
There is no "comment" system in JSON. The best you can hope for is to add a property with an unlikely name, and add that key contaning the metadata. You can then read the metadata back out if you know it's metadata, but other setups will just see it as another property. And if someone uses for..in...
You could just add the Metadata as a "private" variable!?
var Obj = function (meta) {
var meta = meta;
this.getMetaData = function (key) {
//do something with the meta object
return meta;
};
};
var ins_ob = new Obj({meta:'meta'});
var ins_ob2 = new Obj();
if(JSON.stringify(ins_ob) === JSON.stringify(ins_ob2)) {
console.log('hoorai');
};
If you want object-level metadata, you could create a class that extends Object. Getters and setters are not enumerable and, obviously, neither are private fields.
class MetadataObject extends Object {
#metadata = undefined;
get metadata() { return this.#metadata; }
set metadata(value) { this.#metadata; }
}
var obj = new MetadataObject();
obj.a = 1;
obj.b = 2;
obj.metadata = { test: 123 };
console.log(obj); // { a: 1, b: 2 }
console.log(obj.metadata); // { test: 123 }
console.log(JSON.stringify(obj)); // '{"a":1,"b":2}'
You can even simplify the implementation using a Map. Without a setter on metadata, you have to use Map methods to modify it.
class MetadataObject extends Object {
#metadata = new Map();
get metadata() { return this.#metadata; }
}
var obj = new MetadataObject();
obj.a = 1;
obj.b = 2;
obj.metadata.set('test', 123);
console.log(obj); // { a: 1, b: 2 }
console.log(obj.metadata.get('test')); // 123
console.log(JSON.stringify(obj)); // '{"a":1,"b":2}'
I ran into a situation where I needed property level metadata, and used the latter implementation.
obj.id = 1;
obj.metadata.set('id', 'metadata for the id property');

Best way to create an object/struct in javascript

I am new to javascript. As far as I can tell there are 5 ways to make an object (really a struct I guess). I was wondering what the best way is. Thanks.
var makeOption = function(name, dataType){
var option = {
name: name,
dataType: dataType
};
return option;
};
var makeOption2 = function(name, dataType){
this.name = name;
this.dataType = dataType;
};
function makeOption3(name, dataType){
this.name = name;
this.dataType = dataType;
};
var makeOption4 = function makeOption4Name(name, dataType){
this.name = name;
this.dataType = dataType;
};
var v1A = makeOption("hannah", "int");
var v1B = new makeOption("hannah", "int");
//var v2A = makeOption2("hannah", "int"); <- undefined.
var v2B = new makeOption2("hannah", "int");
// var v3A = makeOption3("hannah", "int"); <- undefined.
var v3B = new makeOption3("hannah", "int");
// var v4A = makeOption4("hannah" ,"int"); <- undefined.
var v4B = new makeOption4("hannah" ,"int");
This is what is displayed in the firebug DOM Tab:
I'd go with #3.
#1 does not allow the use of prototype.
#2 is anonymous, and anonymous functions don't help in debugging because you don't see what function is causing problems if it is (the variable name the function is stored is not part of the function, whereas the function's name is).
#4 is confusing - two possibilities to access one function.
Whole chapters of books on JavaScript best practices have been written on this subject. That said: If you aren't concerned about inheritance and aren't going to be creating numerous copies of an object with methods, i.e., you are just creating a "struct", then object literal notation, your first example, is the way to go. In that approach, you are using object literal notation, which is lightweight and fast. It doesn't mess with the object prototype or require the use of the new operator.
Start adding methods to your object, however, and the answer changes to "it depends."
By the way, you left out a couple of ways to create an object:
var o = {};
o.name = "hannah";
o.dataType = "int";
and, not recommended:
var o = new Object();
o.name = "hannah";
o.dataType = "int";
The first one is preferable from design standpoint - based on your name.
makeOption implies that it creates and retuens an object.
All your other solutions do NOT actually return an object and require "new" call. They may have similar/identical technical results when used as pure data structures, but only the first one works as a "object maker", as its name implies.
If you want to use #2/3 (#4 makes no sense - why would you clone the function twice), then you need to name it something else - optionPrototype may be.
I personally use makeoption3 I have tried them all and found that makeoption3 is the cleanest and simplest if you are writing multiple objects. Also it has less code than the others keeping your file size down.
function makeOption3(name, dataType){
this.name = name;
this.dataType = dataType;
};
If you don't need inheritance capabilities, just go with #1 (as you're essentially just using it to build and return an object literal). Otherwise I'd go with #3, as it allows for protoype methods and is also a named function rather than an anonymous one.
Taking this from a Post John Resig made about javascript "Class" instatiation, he points out...
// Very fast
function User(){}
User.prototype = { /* Lots of properties ... */ };
// Very slow
function User(){
return { /* Lots of properties */ };
}
which is what we're talking about he posted this snippet of code...
// makeClass - By John Resig (MIT Licensed)
function makeClass(){
return function(args){
if ( this instanceof arguments.callee ) {
if ( typeof this.init == "function" )
this.init.apply( this, args.callee ? args : arguments );
} else
return new arguments.callee( arguments );
};
}
And then using it, leveraging the speed of using the prototype chain..
var User = makeClass();
User.prototype.init = function(first, last){
this.name = first + " " + last;
};
var user = User("John", "Resig");
user.name
// => "John Resig"
This also takes care of the usage of new it allows the use of the keyword, but doesn't require it.
Link to Original Post
Why don't you want to use object literals? It seems like you're really asking about objects and inheritance..?

Javascript Namespace - Is this a good pattern?

Objectives...
Remove vars, objects etc from the global object.
Remove possibility of collisions.
Firstly I implement the Yahoo namespace code (note for example purposes I am using ROOT as the root of my namespace)...
if (typeof ROOT == "undefined" || !ROOT) {
var ROOT = {};
}
ROOT.namespace = function () {
var a = arguments,
o = null,
i, j, d;
for (i = 0; i < a.length; i = i + 1) {
d = ("" + a[i]).split(".");
o = ROOT;
for (j = (d[0] == "ROOT") ? 1 : 0; j < d.length; j = j + 1) {
o[d[j]] = o[d[j]] || {};
o = o[d[j]];
}
}
return o;
}
Now I declare my 1st namespace...
ROOT.namespace("UI");
ROOT.UI = {
utc: 12345,
getUtc: function() {
return this.utc;
}
}
What I want to do here is to hold vars that I need for my UI (in this case the current time in UTC) so that they are not on the global object. I also want to provide some specific functionality. This should be available on every page without any sort of instanciation...
Now I want to have an object stored within my namespace structure. However, this object will need to be created multiple times. The objective here is to keep this inside my structure but allow it to be created as many times as I need. This is as follows:
ROOT.namespace("AirportFinder");
ROOT.AirportFinder = function(){
this.var1 = 99999;
this.Display = function() {
alert(this.var1);
}
}
And this is the sample code to instanciate the object...
var test1 = new ROOT.AirportFinder();
test1.Display();
Is this a good pattern?
It is indeed reasonable to have things defined on a namespace ROOT or something alike.
It's also better to use closures
(function() {
var AirportFinder = function() {
this.var1 = 99999;
this.Display = function() {
alert(this.var1);
}
};
// do Stuff with local AirportFinder here.
// If neccesary hoist to global namespace
ROOT.AirportFinder = AirportFinder;
}());
If they don't need to be global. I myself use an alias ($.foobar because jQuery is global anyway) for storing any global data.
I'm afraid I can't tell you waht the .namespace function does. It's not really neccessary.
My personal preference is to always use closures to create a private namespace and hoist anything to the global/shared namespace where neccesary. This reduces the global visibility/cluster to a minimum.
Slightly pointing you a little to the side, off the path of your question:
Have a look at YUI3 (http://developer.yahoo.com/yui/3/) - you don't have (to have) anything in the global namespace there, you get a private sandbox. Great concept, I love that library and its conocepts (YUI3, not talking about old YUI2). The way it does that is of course simple and you could do that too: The dynamic module loader of YUI3 loads your module (.js file(s)), creates a sandbox (just a closure) and calls your callback, giving it a handle for the sandbox. No other code anywhere can gain access to that sandbox and your own names. Within that sandbox you can (and should) go on using the various encapsulation patterns. This YUI3 concept is great for mashups with foreign code, especially when mashups become more dynamic in nature (e.g. user triggered), instead of just integrating Google Maps or other well-known APIs by the programmers themselves.
I tried to do a similar thing:
var namespace = function(str, root) {
var chunks = str.split('.');
if(!root)
root = window;
var current = root;
for(var i = 0; i < chunks.length; i++) {
if (!current.hasOwnProperty(chunks[i]))
current[chunks[i]] = {};
current = current[chunks[i]];
}
return current;
};
// ----- USAGE ------
namespace('ivar.util.array');
ivar.util.array.foo = 'bar';
alert(ivar.util.array.foo);
namespace('string', ivar.util);
ivar.util.string.foo = 'baz';
alert(ivar.util.string.foo);
Try it out: http://jsfiddle.net/stamat/Kb5xY/
Blog post: http://stamat.wordpress.com/2013/04/12/javascript-elegant-namespace-declaration/
By using an anonymous self-executing function, you can allow for public and private attributes/methods.
This is the pattern I like the most:
(function ($, MyObject, undefined) {
MyObject.publicFunction = function() {
console.log("This is a public function!");
};
var privateFunction = function() {
console.log("This is a private function!");
};
MyObject.sayStuff = function() {
this.publicFunction();
privateFunction();
privateNumber++;
console.log(privateNumber);
};
var privateNumber = 0;
// You can even nest the namespaces
MyObject.nestedNamespace = MyObject.nestedNamespace || {};
MyObject.nestedNamespace.logNestedMessage = function () {
console.log("Nested!!");
};
}(jQuery, window.MyObject = window.MyObject || {}));
MyObject.sayStuff();
MyObject.nestedNamespace.logNestedMessage();
MyObject.publicFunction();
Learned about it from the comments in this article.

Categories

Resources