When I define an object I can reach all its properties by using the dot character and the same applies to built-in functions like String, Array, Math, etc.
But I cannot loop through them by using for(# in # for example. It says String is native code but still I can reach all its members albeit I cannot iterate through them.
I know window is iterable but their 'sub-functions' appear to be not.
Why is that? Is there a chance to call the properties without explicitly typing their names in? Can I list all its members somehow?
I am aware of that It does not look useful and no one would need it in production. I am asking it because I could not do it and I hope someone can give me some help.
You can get all names only of own(!!!) properties
Object.getOwnPropertyNames(YOUR_OBJECT)
It means, this method doesn't enumerate inherited properties. And if you want to enumerate inherited properties you can use YOUR_OBJECT.__proto__, but it works only in Mozilla
Related
I want to create an object and hide some of its properties.
How do I do this?
For example, to this object:
console.log(new Path2D()); // Path2D {} empty*
In this image, the console is very crowded and confusing.
It depends why you want to do that, it's hard to give a precise answer without more details. In most cases there is no need to hide properties (what are you afraid of?), but here are two ways if you really need to:
you can use Symbol properties (see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol), that is new Path2D() would return an object where the keys are not strings but Symbols. This has the advantage that a user of this object can add its own properties to the object without risking clashing with internal properties that your library relies on. It is still possible for someone to access those properties, though, if they really want to.
You can hide things in a local variable in a closure. It is much more hidden than with Symbol properties, but it might require thinking about the API differently.
I want to let the user define certain variables without overriding existing ones. For example, an allowed new variable:
myJSON = 123
And an invalid one:
JSON = 123
Because it overrides the existing JSON object. Before adding I could simply check if the variable is different from undefined. But I would prefer to show the user which variables are already taken too.
How can I get a comprehensive list of the browser's built-in variables?
Note that Object.keys(window) and Object.keys(document) don't contain JSON. Which other places should I check to get a comprehensive list of taken variables?
So, originally, I thought that the limitation was that Object.keys enumerates only an object's own properties and not inherited ones. However, trying a simple for...in loop without a hasOwnProperty check failed to yield much more than Object.keys. I also tried looping over globalThis to no avail.
A bit of further research showed that JSON is part of the family of "Standard Built-In Objects". When researching that, I came upon a similar Stack Overflow question regarding how to list all standard built-in objects in Node, and the solution was to leverage getOwnPropertyNames. This proved to be the solution-- rather than getting ≈300 results, I instead got 1000+, among which were "JSON" and "Error".
const allWindowProperties = Object.getOwnPropertyNames(window);
console.log(allWindowProperties);
console.log(allWindowProperties.includes('JSON'));
console.log(allWindowProperties.includes('Error'));
So hopefully this solves your problem. My original comment, however, is still worth exploring: How has this use case manifested? Why is it a necessity to allow the user direct access to the runtime environment to declare variables at all, let alone in the global namespace? Perhaps you have a good reason, and I do think this is an interesting question, but I wonder if perhaps we have a classic X-Y problem here.
I'm looking for a list of prototype methods in JavaScript that I can not override.
In case such a list does not exist - I will be glad to read about any method (or a property - like location) that you know that can't be override.
Thank you!
I haven't found a list yet, but I have found more properties and objects that can't be overridden - top, length and location.
I Will try to check all the overrides that are not working in window later today.
I don't know if there a list anywhere, as such, but in the HTML spec such properties are tagged with [LegacyUnforgeable], so you can just search for that string in the spec and you should find them. There aren't many, actually.
I understand that call allows you to pass in an object in place of the 'this' that the method was invoked upon.
"abc".charAt.call("defgh",1);
"e"
But suppose I want the length property to be applied to that object
I can't say
"abc".length.call("defgh");
i'll get an error
Can I do it for a property e.g. length?
Added [since this addition, the 3 answers I see to this question are all good]
It appears some people have thought I was questioning how to invoke a property (which makes no sense). I am not.
And some have thought that I was suggesting that "z".charAt("asdf",0) is better than "asdf".chatAt(0) I am not.
What I am saying is that you can use call on a method to cause it to execute/evaluate on a different object. I could give a more useful example if you really need to see a more useful example.
[1].forEach.call("asdf",function(x){console.log(x+x);});
or
Array.prototype.forEach.call("asdf",function(x){console.log(x+x);});
So forEach can be more concise than a For loop.
So there, even though initially the example I gave for call was not useful, lo and behold, a useful example can exist.
So too, that may be the case with a property
I may want to apply a different object, for a property e.g. 'length' to evaluate on. That should not be impossible in theory(as one answerer suggested before deleting his answer). I don't have a particular use I can come up with that would be beneficial for evaluating a property on a different object, but it should not be impossible.
And just because I don't have a use for it, doesn't mean it should be thrown away. Remember that prior to giving a good usage for call on a method, some said it's pointless, then I gave potentially be a use for it. And that's no argument for it being impossible in theory/principle.
There is no equivalent way to take the functionality behind the .length property and apply it to a different object. Javascript does not have that feature.
Part of the reason is because a property can be just a static value stuck in a property on an object, so there's meaning to evaluate the "ttt".length property on another object. You can access the .length property on another object, but there's no semantic meaning to using the "ttt" object's .length property on another object. The only semantic thing you have is a name. You can use that name on another object as in obj2["length"] or obj2.length, but all you've borrowed from the "ttt" object is the name of the property. It's different with functions that are methods on objects. They are executable code that is passed a this value as context. .call() allows you to take any function (whether a method or not) and specify the value of this when it is executed by using .call(). That's why you can take a method on one object and call it in the context of another object. But, a plain (non-function) property just doesn't have that capability. There's nothing to "execute" in a different context. The property just has a name and a value. You can use the name on any other object, but there's no code you can execute in a different context for that property.
Also, keep in mind once you've retrieved "ttt".length, all you have at that point is a number. That number has no context about where it came from so there isn't really any way to apply the logic that generated that number to some other object.
As for .call(), it is a method of a Function object. So, you can only use it with functions. That's why it works fine with the .charAt() method because that's a function.
But the .length property is not a function (it returns a number) so it does not have a .call() method. That's why what you're trying does not work.
Because .length is not a function, you cannot take the functionality behind it and arbitrarily apply it to another object the way you tried to do with .charAt(). That simply isn't supported with non-functions.
You can, of course, just use the .length property that is already on your other string as in:
console.log("defgh".length);
If you can describe what you're really trying to accomplish, we can probably offer a different way to do it that is supported, but your current description of what you're trying to do does not really seem logical so it's hard to figure out what the actual problem is you're trying to solve.
FYI, there's really no reason to have done this either:
"abc".charAt.call("defgh",1);
You might as well just do the much more direct scheme of calling a method on the desired object:
"defgh".charAt(1); // "e"
It is technically impossible in JS since after the "abc".length expression is evaluated the property name is lost (and only the value is carried over next), hence you cannot re-apply it to the another context.
So even if you extended the primitive type wrapper prototypes - you still would not be able to extract something more but the value.
So it just does not fit into the current language specification.
The purpose of call and apply is to set the this object within a function call. They are necessary for calling functions as methods of objects that don't have that method. However, the caveat is that the object supplied as this can be used by the function.
Applying that principle to properties means trying to read a property of an object that doesn't have it, using the algorithm from some other object that does.
If you consider the length property that many objects have, the algorithm for determining it is very different for each type of object:
String: number of characters
Number: undefined
Function (built–in): as defined in ECMA-262
Function (native, not built–in): number of arguments
Array: whatever has been set, but always at least 1 greater than highest index if there is one
and so on. So which should be the generic version returned of there was an equivalent of call for properties? So There is a very large matrix of property algorithms and objects to apply them to.
However don't despair! If you wish to use, say, the String version of length for some object, then convert it to a string and get its length. E.g. the string version of length for an array might be:
someArray.join('').length;
So you can define the algorithm for such properties any way you like. ;-)
PS. getters allow you to do this on a per object basis, but they can't be shared.
I am trying to really understand the javascript language. I am learning the differences between functions and methods.
This answer explains that methods are functions attached to objects: Difference between a method and a function
But this article from MDN says that
A value of property can be a function, which is then known as the
object's method.
The sentence from MDN implies that JS objects have single methods. Is that correct? In other words: can javascript objects have multiple methods? Or is there a javascript concept roughly akin to "The Object's Method."
An object can have multiple attributes. Those attributes can contain functions. Functions are also objects, so they in turn also can have multiple attributes and so on.
Javascript objects can have multiple methods, I think whoever wrote that article just worded it incorrectly, or a little ambiguously.
Javascript objects can certainly have multiple methods.
I find the quote less confusing if we preserve the original italics:
A value of property can be a function, which is then known as the object's method.
The "the" goes with "object", not "method".
It can have multiple methods. But it can only have one value at a time. But you could even have multiple methods that each return the value...
JS objects can have multiple methods like
window.alert("");
window.confirm("");
window.prompt("");