How do you determine the difference between new Object
and new fn
under these conditions?
var fn = function(){};
fn.prototype = {};
- You may not rely on
__proto__
orObject.getPrototypeOf
existing, as they are not in IE or Opera. - The solution may not statically use
fn
, such asinstanceof fn
. - Implementing your own
Object.getPrototypeOf
is fine.
Not required: It would be nice if your solution works with objects from other frames and doesn't use function serialization.
Here's some example base code to start off with:
var fn = function(){};
fn.prototype = {};
var x = new fn,
y = new Object;
fn = null; // prohibit static reference to fn
// define your detection function here
function isNewObject(obj) {
};
alert(isNewObject(x) !== isNewObject(y) ? "pass" : "fail");
-
As far as I know your problem is impossible to solve with ES3:
instanceof
andisPrototypeOf()
can't be used to solve it because the prototype object offn
is inaccessible, and only ES5 allows access to the internal [[Prototype]] property viaObject.getPrototypeOf()
.Btw, an even harder problem to solve would be if you assign
Object.prototype
tofn.prototype
, egvar x = (function() { function Foo() {} Foo.prototype = Object.prototype; return new Foo; })();
As the prototype chain of
Foo
andObject
instances is identical, there shouldn't be any way to distinguish them. -
I'm pretty sure you can't do this in ES3 with only standard support, and here's why:
Look at
x
andy
creation.var fn = function(){}; fn.prototype = {}; var x = new fn, y = new Object;
When
x
is instantiated, its internal [[Prototype]] is being set to an object referenced byfn.prototype
(just anObject
object that you assigned tofn.prototype
). Object's constructor -fn
- is then being called in a context of that newly created object, but since it doesn't mutate ab object in any way, we can consider that step irrelevant.When
y
is instantiated, its internal [[Prototype]] is being set toObject.prototype
, which is anObject
object too. Its constructor (Object
) is then being called in a context of this newly created object as well, but nothing happens there either.So now you end up with 2
Object
objects which only differ in that their internal [[Prototype]]'s reference different objects -x
's one references whatever you assigned tofn.prototype
andy
's referencesObject.prototype
. Their internal [[Class]] properties are identical too (i.e. equal to "Object")You can't get direct access to [[Prototype]] in ES3. You can infer something about it by using
instanceof
, but sincefn
is nulled in your exampleintanceof
-based inference is out of the picture.Now, you can augment
Object
constructor in such way that it would somehow mutate instantiated object. You can then inspect an object and detect this augmentation. For example:Object = function() { return ({ __: void 0 }); }
and then:
function isNewObject(object) { return '__' in object; }
but this will, of course, only work when object is being created with
new Object
and not via, say, an object literal -{ }
. It's also rather obtrusive :)Perhaps there are other ways, but I can't see them right now.
HTH
Eli Grey : Your solution would only work if someone doesn't explicitly define `__', but it's seems the only possible way (other than bruteforcing by iterating over properties and using !obj.hasOwnProperty(..) and !Object.prototype.hasOwnProperty(..))kangax : You can always change "__" to a more unique token, of course, but the problem would still persist. Any script would be able to spoof Object object by adding/deleting this unique token.
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.