when I write Python code from the interpreter I can type dir() to have a list of names defined in the current scope. How can achieve to have the same information, programmatically, when I develop Javascript code from a browser using an interactive console like firebug, chrome console, etc?
There is keys method in Object, for example:
Object.keys(object)
But this return object's own properties and methods only.
To list all properties and methods of an object I know 2 possibilities:
console.dir(object) method in firebug console for Firefox and
dir(object) method in Google Chrome development tools.
This may work for you, if you need a simple solution:
function dir(object) {
stuff = [];
for (s in object) {
stuff.push(s);
}
stuff.sort();
return stuff;
}
There are a couple of functions which do just this in the code for ChatZilla, you'll have to check the licence properly to see if you can just rip them out and use them wherever.
The relevant functions can be found at
http://hg.mozilla.org/chatzilla/file/59b46c0bf716/js/lib/utils.js#l136
dumpObject and dumpObjectTree
The Google Chrome developer tools console has a predefined dir: https://developers.google.com/chrome-developer-tools/docs/console
Firebug has console.dir: http://getfirebug.com/logging
There are a couple of functions that you you can use to get the data that you need.
Object.keys()
This function will return all enumerable, owned properties that are not Symbols.
> let person = {name: 'John Doe', age: 25, [Symbol('Test')] : 'value'}
> Object.keys(person);
['name'] // Note that the Symbol('Test') is not in the returned array!
Object.getOwnPropertyNames()
This function will return all properties that both enumerable and non-enumerable which are not Symbols.
> Object.getOwnPropertyNames(Set)
[ 'length', 'name', 'prototype' ]
Why is this function useful when we have Object.keys()?
> Object.keys(Set)
[] // Because keys doesn't give you non-enumerable properies
As an aside, why doesn't Object.getOwnPropertyNames(Set) doesn't give you the methods on Set like add, has, etc., ? Because they are on Set.prototype. Object.getOwnPropertyNames(Set.prototype) will yield a much better result.
Object.getOwnPropertySymbols()
This will return all the owned properties that are Symbols in the Object you pass it to.
> let person = {x: 10, Symbol('Test'): 'Test-value' };
> Object.getOwnPropertySymbols(person);
[Symbol(Test)]
Reflect.ownKeys()
This will return all the owned properties that are strings/Symbols in the object you pass it to.
> let person = {x: 1, [Symbol('Test')]: 'Test-value'};
> Reflect.ownKeys(person);
[ 'x', Symbol(Test) ]
Bonus:
Object.getPrototypeOf()
This will return the Prototype of the Object that is passed to it.
> let nameable = { name: 'name' };
> let ageable = Object.create(nameable);
> ageable.age = 0;
> let person = Object.create(ageable);
> let proto_of_person = Object.getPrototypeOf(person);
> proto_of_person === ageable;
true
> let proto_of_ageable = Object.getPrototypeOf(proto_of_person);
> proto_of_ageable === nameable
true
Using this we can enumerate all the properties of an object and its prototype chain recursively.
The global variables are kept in an easily accessible object (window) and so you can inspect/iterate over them easily. (Using something like the functions suggested by Glenjamin)
On the other hand, I don't know of any way to inspect local variables defined in functions or closures - if this is possible I'd at least guess it would be highly browser/console specific.
well you can see object contains like its own properties only : By
it can work in any console not only google chrome web browser look for the img enter image description here
console.dir(obj);
here link: https://developers.google.com/web/tools/chrome-devtools/console/console-reference
(just to see that list)
you can use the operator ".", for example:
> var a = "asdfg";
> a. // -> show the list
in the chrome console it will show you the list of options for autocompletion
in node.js console you can do the same and press tab twice to see the list
The Real Solution
First, create a function that lists out all the properties of an object:
function dir(object) {
props = [];
for (prop in object) {
props.push(prop);
}
props.sort();
return props;
}
Then, as easy as it is, call the function like console.log(dir(console))
Related
Defining a utility function to inspect objects' prototype chains (in Chrome), I get this for arrays.
So it would appear that
[].__proto__ === Array.prototype // === [Symbol(Symbol.unscopables): Object]
I understand the first equality. I have no idea what the third term is, though I have heard that ES6 will have Symbols.
Is this thing the same as Array.prototype? Why does it print that way?
Edit: chrome://version information:
Google Chrome 40.0.2214.111 (Official Build)
Revision 6f7d3278c39ba2de437c55ae7e380c6b3641e94e-refs/branch-heads/2214#{#480}
OS Linux
Blink 537.36 (#189455)
JavaScript V8 3.30.33.16
Comment on 2014-04-14
It seems Chrome's console.log print all Symbol-type-keys, here is an example:
var o = {};
o[Symbol.iterator] = function () {};
o[Symbol.unscopables] = {};
var s = Symbol('s');
o[s] = 3;
console.log(o);
which prints:
Object {Symbol(Symbol.unscopables): Object, Symbol(Symbol.iterator): function, Symbol(s): 3}
I don't why chrome behaves this way, is it for debugging or something else?
Fotunately it does not affect the toString() result so all code is safe.
It seems console.log would especially print the Symbol.unscopable key in console, we can have a plain object to perform like this:
var o = {};
o[Symbol.unscopables] = {};
console.log(o);
which outputs:
Object {Symbol(Symbol.unscopables): Object}
The Symbol.unscopables symbol is a special symbol defined in ES6 as ##unscopables which is used for excluding some properties when this object works in a with environment, the official explanation is:
An object valued property whose own property names are property names that are excluded from the with environment bindings of the associated object.
A simple example:
var o = {x: 1, y: 2};
o[Symbol.unscopables] = {
y: true
};
console.log(o.x); // 1
console.log(o.y); // 2
with(o) {
console.log(x); // 1
console.log(y); // ReferenceError: y is not defined
}
You can use Array.prototype[Symbol.unscopables] to find all keys which cannot be used in with environment
However still, the output of a Array.prototype is not exactly the same as a plain object with Symbol.unscopables key, it outputs [Symbol(Symbol.unscopables): Object], which is a format more like an array
I can't exactly explain why, this may be related to the Symbol.toStringTag which controls how an object should be formatted to string, but Chrome currently does not export this symbol so it's hard to test
I have a function that receives a list of JS objects as an argument. I need to store information about those objects in a private variable for future reference. I do not want to stuff a property into the objects themselves, I just want to keep it out of band in a dictionary. I need to be able to lookup metadata for an object in sub-linear time.
For this I need a hash function such that, for any two objects o1 and o2,
hash(o1) !== hash(o2) whenever o1 !== o2.
A perfect example of such a hash function would be the memory address of the object, but I don't think JS exposes that. Is there a way?
Each object reference is different. Why not push the object onto an array? Traversing the array looking for an object reference might still perform better than inspecting each object in a recursive manor to generate a hash key.
function Dictionary() {
var values = [];
function contains(x) {
var i = values.length;
while(i--) {
if (values[i] === x) {
return true;
}
}
return false;
}
function count() {
return values.length;
}
function get(i) {
return (i >= 0 && i < values.length) ? values[i] : null;
}
function set(o) {
if (contains(o)) {
throw new Error("Object already exists in the Dictionary");
}
else {
return values.push(o) - 1;
}
}
function forEach(callback, context) {
for (var i = 0, length = values.length; i < length; i++) {
if (callback.call(context, values[i], i, values) === false) {
break;
}
}
}
return {
get: get,
set: set,
contains: contains,
forEach: forEach,
count: count
};
}
And to use it:
var objects = Dictionary();
var key = objects.set({});
var o = objects.get(key);
objects.contains(key); // returns true
objects.forEach(function(obj, key, values) {
// do stuff
}, this);
objects.count(); // returns 1
objects.set(o); // throws an error
To store metadata about objects, you can use an WeakMap:
WeakMaps are key/value maps in which keys are objects.
Note that this API is still experimental and thus not widely supported yet (see support table). There is a polyfill implementation which makes use of defineProperty to set GUIDs (see details here).
Javascript does not provide direct access to memory (or to the file system for that matter).
You'd probably just want to create your properties/variables within the analysis (hash) function, and then return them to where the function was called from to be stored/persisted for later reference.
Thanks everyone who chipped in to reply. You all have convinced me that what I want to do is currently not possible in JavaScript.
There seem to be two basic compromises that someone with this use case can chose between:
Linear search using ===
=== appears to be the only built-in way to distinguish between two identically-valued objects that have different references. (If you had two objects, o1 and o2, and did a deep comparison and discovered that they were value-identical, you might still want to know if they're reference-identical. Besides === you could do something weird like add a property to o1 and see if showed up in o2).
Add a property to the object.
I didn't like this approach because there's no good reason why I should have to expose this information to the outside world. However, a colleague tipped me off to a feature that I didn't know about: Object.defineProperty. With this, I can alleviate my main concerns: first, that my id would show up, unwanted, during object enumeration, and second, that someone could inadvertently alter my id if there were to be a namespace collision.
So, in case anyone comes here wanting the same thing I wanted, I'm putting it up there for the record that I'm going to add a unique id using Object.defineProperty.
I know in javascript I can iterate over an object to get all of it's properties. If one or more of the properties is a method, is it possible to see what code is in the method instead of just the method name? E.g.
var a = someobject;
for (property in a) {
console.log(property);
}
Is it possible to get method code in a way similar to this? Thank you in advance.
You need to use toString, per the standard. i.e:
//EX:
var a = {method:function(x) { return x; }};
//gets the properties
for (x in a) {
console.log(a[x].toString());
}
You can also use toSource but it is NOT part of the standard.
PS: attempting to reliably iterate through an object with a for : loop is nontrivial and dangerous (for..in only iterates over [[Enumerable]] properties, for one), try to avoid such constructs. I would ask why, exactly, are you doing this?
Yes. It actually works. Try:
var a = {};
a.id = 'aaa';
a.fun = function(){alert('aaa');}
for (x in a) {
var current = a[x].toString();
if(current.indexOf('function') == 0){
current = current.substring(current.indexOf('{')+ 1, current.lastIndexOf('}'));
}
console.log(current);
}
But it will not work for browser native code.
You can use the toString method on the function
i.e.
function hello() {
var hi = "hello world";
alert(hi);
}
alert(hello.toString());
Update: The reason it wasn't working in JSFiddle was because I forgot to add the output inside of either console.log or alert - http://jsfiddle.net/pbojinov/mYqrY/
As long as a is an object, you should be able to use the square bracket notation and query a value from by argument with the same name as the objects property. For example:
a[ property ];
If you log typeof( property ), it will return "string" which is what we want.
i want to create a dynamic generated form using javascript, everything works fine, until i try to pass an array as parameter. When i do this, an error happens. Coulr anyone explain what this is?
Heres my code:
var loadFrm = function(component) {
for(nItem in component) {
var myComponent = "add" + firstToUpper(component[nItem].type);
var callComponent = myComponent + "(" + component[nItem].opt + ");";
eval(callComponent);
}
}
var json = [
{
type: "scale",
opt: {content: [{label: "male", value: "m"}, {label: "female", value: "f"}]}
}
];
loadFrm(json);
Edit Here's the error:
missing ] after element list
[Break on this error] addScale([object Object]);
If you use a debugger to look at the string callComponent, you'll probably find it looks something like this:
addScale([object Object])
...which isn't what you want. That's because you're effectively calling toString on your opt object, and the default toString on objects just looks like that. The eval error is because that's invalid syntax.
Generally speaking, any time you think you need to use eval, there's almost certainly a better answer. In this case, it looks like you're trying to call a function and pass in opt. Assuming these functions are "globals", you can do that like this:
var loadFrm = function(component) {
var nItem, functionName;
for (nItem = 0; nItem < component.length; ++nItem) {
functionName = "add" + firstToUpper(component[nItem].type);
window[functionName](component[nItem].opt);
}
}
Live example
Notes on the above:
Don't use for..in to loop through arrays unless you really know what you're doing. for..in does not enumerate the indexes of an array, it enumerates the properties of an object.
We look up the function by name using window[functionName]. This works because "globals" are actually properties of the window object, and you can look up properties using a string name for them using bracketed notation.
Having gotten the function via window[functionName], we just call it directly, passing in the object opt rather than a string form of it. I assume addScale expects to see an object.
I moved all of the vars to the top of the function because that's where they really are (details).
If you can, I'd recommend moving addScale and the related functions to their own object rather than putting them on window. The window namespace is already pretty crowded. Here's the live example modified to not add any symbols to window at all, instead putting the addScale function on an object called functions and using it from there.
Off-topic: The syntax var loadFrm = function(component) creates an anonymous function that it then assigns to a variable. This is used a lot, but unless you're creating different functions based on a condition, e.g.:
var f;
if (...) {
f = function() { ... };
}
else {
f = function() { ... };
}
...it's not actually useful. (If you are creating different functions based on a condition like that, then it's not only useful, it's necessary.) I recommend using named functions whenever possible, because a function with a name helps your tools help you by showing you the function name in error messages, call stacks, etc.
Off-topic 2: You have a variable called json, but FYI, it's not using JSON notation. It's using a combination of JavaScript array and object literal notation, which is a superset of JSON. You'll see a lot of people confused about this, I mention it because you said you're new and so it's worth nipping in the bud. :-) JSON is purely a notation. (A very useful one.)
Use this:
fn = eval(functionName);
fn(objParameter)
Is there a way to retrieve the names/values of all global variables on a page?
I would like to write a javascript function to do the following:
Find all global variables prefixed with 'xxx_' and stick them in an array (for e.g.)
build a query string using the name value pairs as follows:
xxx_glob_var1=value1&xxx_glob_var2=value2 etc
How do I do this?
Or you could simply run;
Object.keys(window);
It will show a few extra globals (~5), but far fewer than the for (var i in window) answer.
Object.keys is available in Chrome 5+, Firefox 4+, IE 9+, and Opera 12, ty #rink.attendant.6
Something like this:
function getGlobalProperties(prefix) {
var keyValues = [], global = window; // window for browser environments
for (var prop in global) {
if (prop.indexOf(prefix) == 0) // check the prefix
keyValues.push(prop + "=" + global[prop]);
}
return keyValues.join('&'); // build the string
}
A test usage:
var xxx_foo = "foo";
xxx_bar = "bar";
window.xxx_baz = "baz";
var test = getGlobalProperties('xxx_');
// test contains "xxx_baz=baz&xxx_bar=bar&xxx_foo=foo"
In some cases you may want to find non-enumerable properties; therefore for..in won't work (spec, about chrome) and neither would Object.keys as both only use enumerable keys. Notice that for..in is different to in but we can't use this to iterate.
Here is a solution using Object.getOwnPropertyNames (compatibility is IE9+). I've also added support for when you do only want enumerable properties or if you want to search another in context (not global).
function findPrefixed(prefix, context, enumerableOnly) {
var i = prefix.length;
context = context || window;
if (enumerableOnly) return Object.keys(context).filter( function (e) {return e.slice(0,i) === prefix;} );
else return Object.getOwnPropertyNames(context).filter( function (e) {return e.slice(0,i) === prefix;} );
}
findPrefixed('webkit');
// ["webkitAudioContext", "webkitRTCPeerConnection", "webkitMediaStream", etc..
Then if you want to join e.g.
findPrefixed('webkit').map(function (e) {return e+'='+window[e];}).join('&');
// "webkitAudioContext=function AudioContext() { [native code] }&webkitRTCPeerConnection=function RTCPeerConnection() etc..
You could do something like this:
for (var i in window) {
// i is the variable name
// window[i] is the value of the variable
}
Though with this, you'll get a bunch of extra DOM properties attached to window.
In my case, the two top answers didn't work, thus I am adding another answer, to highlight the comment of Dan Dascalescu:
Object.keys(window);
When I executed it, it gave:
top,location,document,window,external,chrome,$,jQuery,matchMedia,jQuery1113010234049730934203,match_exists,player_exists,add_me,isLetter,create_match,delete_me,waiting,unsure,refresh,delete_match,jsfunction,check,set_global,autoheight,updateTextbox,update_match,update_player,alertify,swal,sweetAlert,save_match,$body,value_or_null,player,position,ability,obj_need_save,xxx_saves,previousActiveElement
where the player, positon, ability, obj_need_save, xx_saves are my actual global variables.
I just saw that there exists a similar answer to another question.