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.getPrototypeOfexisting, as they are not in IE or Opera. - The solution may not statically use
fn, such asinstanceof fn. - Implementing your own
Object.getPrototypeOfis 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:
instanceofandisPrototypeOf()can't be used to solve it because the prototype object offnis 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.prototypetofn.prototype, egvar x = (function() { function Foo() {} Foo.prototype = Object.prototype; return new Foo; })();As the prototype chain of
FooandObjectinstances 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
xandycreation.var fn = function(){}; fn.prototype = {}; var x = new fn, y = new Object;When
xis instantiated, its internal [[Prototype]] is being set to an object referenced byfn.prototype(just anObjectobject 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
yis instantiated, its internal [[Prototype]] is being set toObject.prototype, which is anObjectobject 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
Objectobjects which only differ in that their internal [[Prototype]]'s reference different objects -x's one references whatever you assigned tofn.prototypeandy'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 sincefnis nulled in your exampleintanceof-based inference is out of the picture.Now, you can augment
Objectconstructor 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 Objectand 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.