How to find the text description of what 'this' currently points to in javascript.
i have tried this.name but just get undefined.
this.toString() - I think that's the best you can get
EDIT: You can also try looping through the object's properties to see what it contains:
for (property in this) {
console.log(property);
}
If you're using Firebug you can use console.log(this). The console should then provide a clickable representation of whatever you've just logged, and clicking on it should take you to a more detailed explanation.
Well there's always typeof:
var type = typeof obj;
But, this is not foolproof as you will just get 'object' for objects...
Well, I'm still not entirely sure what you're wanting, but I've put this demo together, at JS Fiddle to give you an idea of a couple of the options available.
It rests on using:
$('#result').text(this.tagName.toLowerCase());
or
$('#result').text(typeof this);
Objects don't have names in JavaScript, it's as simple as that. A variable with a particular name could have an object as it's value, but that's as far as the relationship goes, the object retains no reference to the variable name that points to it. In fact, more than one variable may point to it. If a reference to an object is stored as a property on another object, you could iterate over that object's properties checking to see if the current property's value is the same object in the this value. For instance:
for (var k in someObj) {
if (this == someObj[k])
console.log(k + " points to this.");
}
I don't think there's a reason you'd ever need to do this, however.
No Firebug required (demo at http://jsfiddle.net/Y57ed/2/):
function usefulTypeof(obj) {
return obj === null ? "null" :
obj.constructor.toString().replace(/[^\w$\s]+/g, "").split(/\s+/)[1];
}
Related
I am looking for a way to get the name of an object property like this:
let o = {
first: 1,
second: 2
};
function q(prop) {
// return name of prop
}
console.log(q(o.first));
// should return "first"
I am not even sure this is possible, but I am just asking.
The main use case for this is given by dynamic specification of requested attributes while keeping the advantages of using intellisense which can be quite significant for large projects and refactoring purpose.
I am not even sure this is possible...
Good instinct! It isn't. When you do:
q(o.first);
the value of the o.first property (1) is passed into q. Nothing about the object or its property is passed to q, just the value 1.
If you know what object the value came from, and if that object had only one property with a matching value, you could figure it out. But of course, one or both of those won't be true the vast majority of the time. In the general case, no, there's nothing to tell you that it came from o.first.
You try this with slight modification of your code
function q(obj,prop) {
if(obj.hasOwnProperty(prop))
return prop;
else
return null;
}
console.log(q(o,o.first));
Hope this help.
Node.js querystring.parse() method returns what looks like to be an object, but one without a constructor. According to https://nodejs.org/api/querystring.html :
"... The object returned by the querystring.parse() method does not prototypically inherit from the JavaScript Object. This means that typical Object methods such as obj.toString(), obj.hasOwnProperty(), and others are not defined and will not work."
This easily causes bugs because typically you would assume that every Object understands some basic methods like toString() and that it has a "constructor" which more or less tells us its "type".
What's the best way to handle these rather incapable Objects? I tried:
let myOb = new Object(dumbObject);
But that produces a result which does not have the toString() -method either and does not have the property 'constructor'.
What's the best way to turn these dumb objects into ordinarily behaving ones? And, why would anybody want to create such objects in the first place?
I think (from the top of my head)
let newObject = JSON.parse(JSON.stringify(dumbObject))
should work.
If you want a more generic way to call toString() on an object, you can call it from Object.prototype using .call().
var s = Object.prototype.toString.call(smartObject);
But why? It's just going to give you "[object Object]" on any plain object. Why is it important to get that string?
var p = {};
var s = Object.create(null);
console.log(p.toString());
console.log(Object.prototype.toString.call(s));
typically you would assume
No, you wouldn't. If you make such assumptions, document them in your interface.
What's the best way to turn these dumb objects into ordinarily behaving ones?
Use Object.assign with an ordinary object as the target. Alternatively, you can also change the prototype by using Object.setPrototypeOf, but that's not recommended.
Or just create the properties like .toString or .constructor that you need. See this example.
And, why would anybody want to create such objects in the first place?
Because you need this safety when using objects instead of Maps. See this example.
Explicitly set the prototype of your dumb object with Object#setPrototypeOf
var dumbObject = Object.create(null);
Object.setPrototypeOf(dumbObject, Object.prototype);
dumbObject.toString() //runs fine
Thanks for all the answers, one of which contained a link to another question which really was my question as well, even if I didn't know that at first. That other question is: How to create a JS object with the default prototype from an object without a prototype?
From it I found the answer which I think is the simplest solution so far: Use Object.assign(). Like this:
let orphan = require('querystring').parse("{}") ;
// console.log ( "Got value: " + orphan ) ;
// Above causes the error:
// -> TypeError: Cannot convert object to primitive value
let oa = (x) => Object.assign({}, x);
console.log ("Got value: " + oa (orphan) ) ;
Note the issue is not particularly about "querystring" but with objects which have no prototype in general. Yes we should probably call these poor objects "orphans" instead of "dumb". But I think "dumb" is still quite good term as well. An object which has no prototype has very few (or no?) methods so it can answer very few if any questions we would like to ask it.
I've seen before that undefined semantically should only be used for variables that have been declared but not defined, and if a variable should at any point be set or unset, I should initially set it to null and check the variable against null rather than setting it back to undefined.
I'm wondering about the case where I am checking something that should be undefined, as in the case I am checking what an unset key in an object points to
i.e.
var eva = {'asuka': 2, 'rei': 0};
if I were to check eva['shinji'], I would have to check for undefined, because there are cases where I would not know all the possible keys that would be checked against.
I guess in this case, eva['shinji'] being undefined would be correct, though in the specific case of keys in objects, using ('shinji' in eva) would be best?
However, I have a feeling there may be other cases where objects that were unknown were checked against, that I could not use a 'in' for instead, but the case of object keys was most apparent to me.
In those cases, would it be best to check for undefined?
First of all, your statement is incorrect, should be:
var eva = {'asuka': 2, 'rei': ''};
Then you can find eva['asuka'] or eva.asuka will give 2.
If you want to check if a property inside an object.
There are multiple ways to do that.
You can simple check eva && eva.hasOwnProperty('asuka')
eva && typeof(eva.asuka) !== 'undefined'
3.
var found = false;
for (i in eva){
if (i == 'asuka') {
found = true;
break;
}
}
As mattclemens commented, if you do not understand the differences and best practices surrounding undefined vs null please check out the link he posted, or one of the other multitudes of blog/forum posts, books, or videos regarding this subject (i.e. duckduck something like "js best practices undefined null").
Based on the first paragraph of your question it seems you have a grasp on what they mean, and this question comes down to context...
I'm wondering about the case where I am checking something that should be undefined...
This seems like a loaded question to me. What does "should be undefined" mean? This tells me that your code never sets that property that "should be undefined" and you are assuming nothing else is setting it. But really, "should be undefined" doesn't make sense to me. You either know it's not because it's never been outside the current scope and you haven't defined it yourself, or you don't know and it's best practice to check whether it's defined before checking if it's null.
So I see this as 2 basic scenarios:
Internally/Privately created and used exclusively internal to code you control
Externally/Publicly created or crossing the public/private line
1. Internal/Private use only
In the first scenario the answer is simple: initialize the object with default values (falling back to null) for all properties that will ever exist on the object...
var eva = {'asuka': 2, 'rei': null};
...or since you have direct control over the object throughout its lifecycle, add properties explicitly as needed using the default operator...
eva.shinji = eva.shinji || null;
Then whenever you need to check the value of a specific property, your only concern is whether it is null. You will notice this strategy being employed in some of the most widely used js libraries, such as jQuery, where internal variables are only ever checked against null, or even assumed to exist within some contexts.
2. External/Public use at any point in the object's lifecycle
For objects you can't trust there are two approaches I would suggest, and which one is choosen depends, again, on the details of the context. If you are receiving some object, and will be using that object repeatedly or modifying the data you receive from it for internal use only, or if it is unsafe to change the value of the original object in any way, you may want to make your own copy of the object and then deal with that copy exclusively. Again, this is illustrated in libraries/frameworks, such as jQuery and AngularJS, where things like window and the undefined value itself, are passed in to the IIFE, and an internal copy is created/extended for internal use throughout the lifetime of the consumer.
However, this may be unnecessary overhead for your situation. Instead you could just verify the contents of eva when it crosses that external/internal boundary. The following example does so with the default operator.
function yourFunction(eva) {
eva = eva || {};
eva.asuka = eva.asuka || 2;
eva.rei = eva.rei || null;
}
Alternatively, you may have a string value or array of string values that are keys you wish to verify exist on the object. In that case please consider the following example using Object.keys(). This example also allows for the array of names of keys to be undefined.
function foo(eva, keysToFind) {
eva = eva || {};
keysToFind = keysToFind || ['asuka', 'shinji'];
var keysToCheck = Object.keys(eva);
for(var k in keysToFind) {
var keyName = keysToFind[k];
var keyIdx = keysToCheck.indexOf(keyName);
if(keyIdx == -1) {
eva[keyName] = null;
}
}
}
Finally, as RaymondM points out, you can take this a step further if you need to determine whether a property was added to the object literal, it's prototype, or inherited from a super/base class...
You can simple check eva && eva.hasOwnProperty('asuka')
Again, taking context in to consideration, if you have already identified the context as scenario 1 or 2 from above, and are checking any more than a single property's existence, then it will likely be more efficient to check for === null or typeof eva.asuka === 'undefined', respectively. Or even check if(eva && eva.asuka) { ... }, if you're certain asuka has been defined.
everyone:
as we all know, getting a nonexistent value from Object will got a "undefined", is there any way to throw an error instead of return a undefined?
for instance:
var a= {example:"example"};
//do something here
a.b //error throw instead of "undefined"
thx very much for helping.
Object.define property has a way to specify the get and set methods
look at the link below
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty
Object class has a method "hasOwnProperty" which could also be used to check if a property exists or not before trying to access it
ES6 comes with Proxy Objects which will help you overload the dot operator. What this means is that you can invoke a function when you retrieve a property. This will allow you to check if the property is defined and if it isn't "throw" an error. Hope this helps. More info here
Looking at the above example, if you are you trying to initialize the property "b" on the object a with a value after "a" has been defined, then you could just as easily do the following:
var a= {example:"example"};
//do something here
a.b = 'some value';
a.b //now an error is not throw
Most Objects can be re-defined even after they have been initialized. Properties and methods can be added and removed once objects have been initialized.
I say most, because it is possible to prevent objects from being extended/altered (using Object.preventExtension method).
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/preventExtensions
I don't know how to extend the map object with prototype and hope you can help.
I have something like this:
var map = {'one':1, 'two':2};
and I would like to have a method to check for the existence of a key:
if (map.containsKey('one')){...}
How would I extend the map object?
It's dangerous to modify Object.prototype, because it affects all objects and will usually break other libraries you may be using. In general, if you want to add methods to a dictionary-like object, you should create an object for your hash instances to inherit from, like the Prototype Hash object.
For this specific instance, you should really just use either if (key in map) or if (map.hasOwnProperty(key)).
There is already an operator to test the existence of a key inside an object.
(In JavaScript, objects are implemented as maps so actually there is no real map.)
if( 'one' in map )
{
alert(map['one']);
}
These are not "maps" they are objects. Building on Maurice's answer, if you want this to apply to all objects:
Object.prototype.containsKey = function(key) {
return this.hasOwnProperty(key);
};
The simplest way to do this is to add a function directly in the object:
map.containsKey = function(key) {
return this[key] ? true : false;
};
In Javascript, you do not need such method really.
if ( map['one'] ) {
// do something
}
should do it
As other's have said, extending Object.prototype might not be a good idea if your code has to play nice with code written by people ignorant of hasOwnProperty().
Anyway, there are three 'correct' ways I know of to check if a property is available:
obj.hasOwnProperty(name)
checks if a property with given name exists in the object.
name in obj
additionally includes properties inherited via an object's prototype chain.
typeof obj[name] !== 'undefined'
will additionally evaluate to false if the property is present but has been set to undefined.
Some non-JS object's (e.g. window.external in IE) might not implement hasOwnProperty(), so one of the other checks has to be used.