Johnny
Johnny

Reputation: 385

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
}

Upvotes: 0

Views: 182

Answers (2)

The Spooniest
The Spooniest

Reputation: 2873

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.

  1. Create an object [[newPrototype]].
  2. Set [[newPrototype]].[[myPrototype]] to [[Constructor]].prototype
  3. Create an object [[newObject]].
  4. Set [[newObject]].[[myPrototype]] to [[newPrototype]]
  5. Set [[newObject]].[[myPrototype]].constructor to [[Constructor]]
  6. 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.

Upvotes: 1

Ruben Serrate
Ruben Serrate

Reputation: 2783

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 :)

Upvotes: 1

Related Questions