Is there a way to use window.hasOwnProperty() in Internet Explorer? - javascript

I have a method, that perfectly works in Firefox, with which I can determine the name of an instance of a particular javascript object (please don't ask why I need it...).
Fr example:
var temp = new String("hello!");
var theName = getVarName(temp); //returns "temp"
This method uses "window.hasOwnProperty()" which doen't work in Internet Explorer: any suggestions?

If for whatever reason you do need to use window, use:
Object.prototype.hasOwnProperty.call(obj, p)

I have a method, that perfectly works in Firefox, with which I can determine the name of an instance of a particular javascript object
I don't think you do, because that's not possible in JavaScript. JS is a call-by-value language; when you write:
var temp= 'hello';
getVarName(temp);
that's exactly the same as saying:
getVarName('hello');
At which point the reference to ‘temp’ as a variable is lost. What I'm guessing your getVarName function does is basically this:
function getVarName(value) {
for (var name in window) {
if (window[name]===value)
return name;
}
}
This will work on IE and other browsers without Object.hasOwnProperty(); it will simply return the name of any global variable that matches the argument. The hasOwnProperty() call can be added to this function to refine it a little by only allowing direct properties of window (which act as global variables, including the ones you set explicitly), and not of any of its prototypes. I'm guessing that's what your version of the function is doing, but in practice it has very little effect since almost nothing inherits into ‘window’ by prototype.
You're confusing things a little bit by boxing your 'hello' in an explicit String object (which is very unusual and rarely a good idea), which makes it possible to have two different 'hello' objects that are disinguishable using the === identity comparator, so this will work:
var a= new String('hello!');
var b= new String('hello!');
getVarName(a); // 'a'
getVarName(b); // 'b' - distinguishable object from a
But that still doesn't stop you from doing:
var a= new String('hello!');
var b= a;
getVarName(a); // 'a' or 'b', depending on implementation
getVarName(b); // the same 'a' or 'b' as in the previous call
So, whilst you can fairly harmlessly lose the hasOwnProperty() call as above, what you're doing can't really work properly and you should probably look at a better way of achieving whatever it is you're up to.

Do not use global variables. Always put them in namespaces so that you don't run into such problems.
If I understood correctly, you want the global variable name when given the value under any scope. For example, the following should work too
var temp = "hello";
function foo(x) {
alert(getVarName(x)); //returns "temp" as well.
}
foo(temp);
This is sort of reverse hash lookup on Window object which is not only expensive, since you need to iterate over all the properties of window object each time, but also unreliable (two variables can have a same value).

Related

using Set.has in Array.filter - incompatible receiver

Suppose I've a Set as a lookup table.
const myset = new Set(["key1", "key2", "key3", "keepMe"]);
I wanted to filter another array of some other keys (say mykeys) which are in myset.
const mykeys = ["ignoreMe", "keepMe", "ignoreMeToo", "key2"];
Question:
Why do I have to use
const filtered = mykeys.filter(k => myset.has(k))
instead of
const filtered = mykeys.filter(myset.has)
// TypeError: Method Set.prototype.has called on incompatible receiver undefined
i.e., why do I've to create an anonymous lambda function in filter? keys.has has same signature (argument - element, return boolean). A friend told me it's related to this.
Whereas mykeys.map(console.log) works without error (although not being of much use).
I came across this article at MDN and I still don't get why "'myset' is not captured as this". I understand the workaround but not the "why". Can anyone explain it with some details and references in a human friendly way?
Update: Thank you all for the responses. Maybe I wasn't clear about what I'm asking. I do understand the workarounds.
#charlietfl understood. Here's his comment, the thing I was looking for:
Because filter() has no implicit this where as set.has needs to have proper this context. Calling it inside anonymous function and manually adding argument makes the call self contained.
You could use thisArg of Array#filter with the set and the prototype of has as callback.
This pattern does not require a binding of an instance of Set to the prototype, because
If a thisArg parameter is provided to filter, it will be used as the callback's this value. Otherwise, the value undefined will be used as its this value. The this value ultimately observable by callback is determined according to the usual rules for determining the this seen by a function.
const
myset = new Set(["key1", "key2", "key3", "keepMe"]),
mykeys = ["ignoreMe", "keepMe", "ignoreMeToo", "key2"],
filtered = mykeys.filter(Set.prototype.has, myset);
console.log(filtered);
This is a fundamental design decision dating back to the first definition of the JavaScript language.
Consider an object
var myObjet = {
someValue: 0,
someFunction: function() {
return this.someValue;
}
};
Now, when you write
var myValue = myObject.someValue;
You get exactly what you have put in it, as if you had written
var myValue = 0;
Similarly, when you write
var myFunction = myObject.someValue;
You get exactly what you have put in it, as if you had written
var myFunction = (function() {
return this.someValue;
});
...except now, you are not in an object anymore. So this doesn't mean anything. Indeed, if you try
console.log(myFunction());
you will see
undefined
exactly as if you had written
console.log(this.someValue);
outside of any object.
So, what is this? Well, JavaScript decides it as follows:
If you write myObject.myFunction(), then when executing the myFunction() part, this is myObject.
If you just write myFunction(), then this is the current global object, which is generally window (not always, there are many special cases).
A number of functions can inject a this in another function (e.g. call, apply, map, ...)
Now, why does it do this? The answer is that this is necessary for prototypes. Indeed, if you now define
var myDerivedObject = Object.create(myObject);
myDerivedObjet.someValue = 42;
you now have an object based on myObject, but with a different property
someValue
console.log(myObject.someFunction()); // Shows 0
console.log(myDerivedObject.someFunction()); // Shows 42
That's because myObject.someFunction() uses myObject for this, while myDerivedObject.someFunction() uses myDerivedObject for this.
If this had been captured during the definition of someFunction, we would have obtained 0 in both lines, but this would also have made prototypes much less useful.

javascript prototype for object

how the prototype works ? why the "xc" can not be accessed from e object?
please look down to the code , see the comments , i testing it in the chorme
var x={a:"xa",b:"xb",c:"xc"};
var e={a:"ea",b:"eb"};
console.log(Object.prototype); // this is {} why? i am expecting it to be null
console.log(e.prototype);
e.prototype=x;
console.log(e.prototype);
console.log(x.c);
console.log(e.c);//this is undefined , why? i am expecting it to be "xc"
console.log(e.a);
console.log(e.b);
console.log(e.prototype.a);
console.log(e.prototype.b);
i first think it would useful in css merging ,later i think for working out the dependency, then re-write css is more reasonable, however the knowledge is real. thanks very much.
var css={
'classSelectorExpressionIDOnly1':{
css_Ruls_name1:xxxx,
css_Rulss_name2:xxxx
}
'classSelectorExpressionIDOnlyX':{
css_Ruls_name1:xxxx,
css_Rulss_name9:xxxx
}
'classSelectorExpressionIDOnly2':{ '()inherit':["classSelectorExpressionIDOnly1","classSelectorExpressionIDOnlyX"]
css_Ruls_name3:xxxx,
css_Rulss_name5:xxxx
}
}
var mergeResult = Object.create(css.classSelectorExpressionIDOnly2);
for(var entry in mergeResult){
mergeResult[entry]= mergeResult[entry];
}
mergeResult.__proto__=css.classSelectorExpressionIDOnly1;
for(var entry in mergeResult){
mergeResult[entry]= mergeResult[entry];
}
mergeResult.__proto__=css.classSelectorExpressionIDOnlyX;
for(var entry in mergeResult){
mergeResult[entry]= mergeResult[entry];
}
------dependency re-write--------
.classSelectorExpressionIDOnly1,.classSelectorExpressionIDOnly2{
css_Ruls_name1:xxxx,
css_Rulss_name2:xxxx
}
.classSelectorExpressionIDOnlyX,.classSelectorExpressionIDOnly2{
css_Ruls_name1:xxxx,
css_Rulss_name9:xxxx
}
.classSelectorExpressionIDOnly2{
css_Ruls_name3:xxxx,
css_Rulss_name5:xxxx
}
That's not what the .prototype property is for. Despite the name, the .prototype property of functions isn't actually the prototype of the objects you're used to working with. This is one of the hardest things to understand about JavaScript, so it's not just you.
The key to understanding the prototype system in JavaScript is that the new operator creates two objects, not one. I'm going to talk about this in terms of four variables:
[[myPrototype]]
The prototype of an object. Every object theoretically has one (though for some objects, it might be undefined).
[[Constructor]]
The function that is being called with the New operator
[[newObject]]
The object that will eventually be returned
[[newPrototype]]
The object that will become [[newObject]].[[myPrototype]]
Note that these aren't valid JavaScript names (in fact, they're not valid names in most programming languages). All of this happens behind the scenes, and most implementations don't use these names either. I'm doing this to make clear that you can't normally see these objects.
When you use the new operator, JavaScript does roughly the following steps.
Create an object [[newPrototype]].
Set [[newPrototype]].[[myPrototype]] to [[Constructor]].prototype
Create an object [[newObject]].
Set [[newObject]].[[myPrototype]] to [[newPrototype]]
Set [[newObject]].[[myPrototype]].constructor to [[Constructor]]
Call [[Constructor]], with [[newObject]] as "this".
Note that [[newObject]].[[myPrototype]] isn't a perfect match for either [[newObject]] or [[Constructor]].prototype. That's why we need a third object between them: it carries the information you want to inherit (through [[newPrototype]].[[myPrototype]]), but it also carries information specific to the object you're creating (in [[newObject]].constructor).
And so we get to what the .prototype function is for. It's not the function's [[myPrototype]], and it's not the [[myPrototype]] for the objects you create with new. It's actually two levels back in the prototype chain, not one.
I hope this explanation helps you understand what the .prototype function is for. This isn't simple stuff, and not every explanation clicks with everybody. That's part of why we have so many explanations here.
When you first create an object, you can set its prototype directly with Object.create(). This function works with IE9 and higher (plus all other modern browsers), and it can be polyfilled if you need to work with older browsers. To see that prototype later, you use Object.getPrototypeOf(), which also has decent browser support (though IE only supports it in version 9 and higher). Using only these two functions, you might create your objects like this:
var x = {a:"xa",b:"xb",c:"xc"};
var e = Object.create(x);
x.a = "ea";
x.b = "eb";
console.log(Object.getPrototypeOf(Object));
console.log(Object.getPrototypeOf(e));
console.log(x.c);
console.log(e.c);//this is undefined , why? i am expecting it to be "xc"
console.log(e.a);
console.log(e.b);
console.log(Object.getPrototypeOf(e).a);
console.log(Object.getPrototypeOf(e).b);
Once an object has been created, there isn't a standard way to reset its prototype yet. ECMAScript 6 defines one (the Object.setPrototypeOf() function), but so far only Chrome and Firefox support it: IE and Safari do not. Still, if that's OK, you could do things like this:
var x = {a:"xa",b:"xb",c:"xc"};
var e = {a:"ea",b:"eb"};
console.log(Object.getPrototypeOf(object));
console.log(Object.getPrototypeOf(e));
Object.setPrototypeOf(e, x);
console.log(Object.getPrototypeOf(e));
console.log(x.c);
console.log(e.c);
console.log(e.a);
console.log(e.b);
console.log(Object.getPrototypeOf(e).a);
console.log(Object.getPrototypeOf(e).b);
There is a non-standard way to reset an existing object's prototype, and it even enjoys good browser support nowadays. To do this, you set the .__proto__ property on any standard object. You could use it like this:
var x = {a:"xa",b:"xb",c:"xc"};
var e = {a:"ea",b:"eb"};
console.log(object.__proto__);
console.log(e.__proto__);
e.__proto__ = x;
console.log(e.__proto__);
console.log(x.c);
console.log(e.c);
console.log(e.a);
console.log(e.b);
console.log(e.__proto__.a);
console.log(e.__proto__.b);
Now, onto your last question: why is Object.prototype equal to {}, rather than undefined? Because the Object constructor function has a .prototype property, which becomes the default prototype of all Objects created through it. The specs call this object [[ObjectPrototype]], and it's where things like the .hasOwnProperty() function live.
Have a look here:
https://stackoverflow.com/a/9959753/2768053
After reading that, you will turn your code into this:
var x={a:"xa",b:"xb",c:"xc"};
var e={a:"ea",b:"eb"};
console.log(Object.prototype.__proto__);
console.log(e.__proto__);
e.__proto__=x;
console.log(e.__proto__);
console.log(x.c);
console.log(e.c);
console.log(e.a);
console.log(e.b);
console.log(e.__proto__.a);
console.log(e.__proto__.b);
and you will get the results you expect :)

Can you extend an object that has access to private properties with a function that can also access those private properties?

I am creating an object inside of an enclosure. Also in the enclosure are private properties that the object's functions can access - and this works as expected.
My issue: I want others to be able to extend my object with functions of their own (functions from a different context), but those functions will also need access to the same private properties - and I have not been able to find a way to make this work.
I've tried various configurations of .call, and also wrapping their function in a new function, amongst other things. I feel like I've gotten close to a solution, but have just fallen short.
Here's a bit of simplified example code that accurately reflects my situation:
//extension object
//fn2 can be any function, with any number of arguments, etc.
var obj1 = {};
obj1.fn2 = function (s1, s2){ console.log(priv); };
//actual object
var obj2 = (function (){
//private property
var priv = "hello world";
//return object
var obj3 = {};
//return object's native fn (works)
obj3.fn = function (s){ console.log(priv); };
//extension happens here - but is obviously not correct
obj3.fn2 = obj1.fn2;
//return object
return obj3;
})();
//try output
obj2.fn("goodbye world"); //works
obj2.fn2("goodbye world", "thx 4 teh phish"); //fails
Any insight would be appreciated. And I totally understand if what I want just isn't possible - but it sure seems like it should be :P
EDIT: Thank you all for the responses. I fully understand that the properties are more easily accessed as public, and that normally inherited objects won't have access to them otherwise. However, since the new function is being attached to the original object I have to believe there's a way to use the original context and not the context the new function was created in.
Now, I'm the first to say that eval is evil - and, in fact, I've never used it, or even considered using it, before. However, I'm trying everything I can think of to make this work - and I stumbled across this (seemingly) working solution:
obj3.fn2 = eval(obj1.fn2.toString());
So, if I check to make sure that obj1.fn2 is a typeof function, is there any way this could be harmful to my code? It doesn't execute the function, so I can't see how - but maybe I'm missing something?
Javascript doesn't have a "protected" analog. You either get super private or completely public. From here you can choose to:
Reconsider your class design, and have the subclasses depend only on the public interface of the parent class.
Add getter and setter functions to the public interface. Not necessarily the best thing though as you might just as well make the properties public (besides best practice issues and whatnot)
Just use public properties instead. This is the "natural" way to do OO inheritance in Javascript and is usually not a problem if you use a donvention like adding an underscore to the beggining of the name. As a bonus you can use the prototypal inheritance feature (it is nice knowing how to use this instead of only closure-based classes)
function Base(){
this._priv = "Hello world"
};
Base.prototype = {
fn: function(){
console.log(this._priv);
}
}
var obj2 = new Base();
obj2.fn = function(){ ... }
I hate to answer my own question - seems like a bit of a faux pas - but c'est la vie. (because I woke up French today?)
So, while I found that the eval() solution I presented last night in the edit to my original question does seem to be a valid solution, and a proper use of eval for retaining the object's context within the new function, it is far from perfect.
Firstly, it works in FF, but both IE and Chrome seem to hate it (those were the next ones I tried, and I quit trying others after they both failed). Though I'm sure it could probably be made to work across browsers, it seems like a hassle.
Secondly, it does give quite a bit of power to the new function, and as I look at my code more I do like the idea of controlling exactly what these new functions being added to my object get access to.
Thirdly, .eval() is typically pretty slow - and it turns out that .apply() (which is typically faster) just may work well enough.
This is because I realized at some point last night that no new functions on this object will need to set any of the private variables (at least, I'm fairly certain they won't) - and .apply() works fine to pass the values through for them to read.
I'm sure there's more to it than just those 3 things, but for now I think I'm going to go with more of a 'wrapper' solution - something like this:
var f = function (){
var fauxThis = {};
fauxThis.priv = priv;
obj1.fn2.apply(fauxThis, arguments);
};
obj3.fn2 = f;
//(To be placed where I had "obj3.fn2 = obj1.fn2;")
I am certainly willing now to consider the use of eval() in very specific cases - and may even revisit this specific use of it before I make my final decision of which direction to take. (especially if I can think of a case where the private value would need to be set)
Thanks all for your input!
The quickest and easiest solution is to prefix any supposedly private properties with the underscore (_).
Personally I like to bottle my private properties into a single object which would be placed on the object, like so:
obj.publicProp = 20;
obj._.privateProp = true;
I wouldn't worry so much about it though, the underscore is basically a universal symbol for private so those using the script will know that it's private and shouldn't be touched. Or, better yet, just leave it out of the public documentation ;)
There are other methods and you can use which do emulate "true" protected variables, but they're not the best as they avoid garbage collection, and can be clunky to use.

Displaying objects in html format

I'm trying to write an object explorer that shows the user the properties and values of an object. My idea is that the will be able to drill down to see objects within objects, click on hyperlinks to examine the methods' source code and otherwise see the properties values.
Here's what I've got so far (jsFiddle).
Q: Help! I don't know what I'm doing! One thing I noticed is that I'm apparently not getting any properties where hasOwnProperty is true. Another thing is I need the function to be recursive. Another is: I think I remember reading somewhere of a JavaScript function that can get the text of a JavaScript function.
So, to answer your question: "What's the question?" I guess I can say "Can you help me write this generic JavaScript object explorer as possibly a jQuery plugin?"
Your question is quite general. To your two specific points:
In order to make your function recursive, I believe you can simply copy this block of code from your 'bodyLog' function to the place you have commented your recursion. You will want to add one to 'level' as you pass it down to your recursive call.
// $(obj).each(function(index,Element) { // EDIT shouldn't need this iteration, you're inside the loop
result += showObjectsMethodsAndValues(Element,level+1,true);
result += showObjectsMethodsAndValues(Element,level+1,false);
//});
The method that gets the string body of a function is simply calling '.toString()' on the method object. So if you do:
var myFun = function(a, b) {
return a+b;
};
alert(myFun.toString());
You will see the body of the function printed out. For built-in objects you will probably see "[native code]" as the body of the function, rather than real javascript code.
The reason you aren't seeing any hasOwnProperty properties is that I doubt the jQuery object has any. All of it's properties likely live in it's prototype object. Try this:
var myObj = {foo: 1, bar: 2};
myObj.prototype = {baz: 3};
Then call your function on myObj. Foo and bar should come back with hasOwnProperty true, baz will return false. I believe all of jQuery's properties live in it's prototype object, so they will all return false.
http://www.netgrow.com.au/files/javascript_dump.cfm is a good candidate.

How can I use Javascript dynamic properties so Foo.Bar returns current Date()?

I want to create an object property that re-calculates it's value each time it is called.
I took at stab at it:
var Foo = { Bar : (function() { return Date(); })() }
alert(Foo.Bar); // shows time at object literal Foo was init'd
// but need it to show time when it's called
It it even possible?
Not possible - JS properties are not "executable" like C# properties are. The best you can do is a normal method.
Aside: from a design standpoint I would actual consider a self-changing property to be pretty poor. The principle of least surprise would be better served by a method anyway.

Categories

Resources