From: Jeremy on 15 Jul 2010 16:36 Hi, I'm trying to figure out how to modify the property of an object from within an object descended from that parent object. Here's the code: //new object function A() { this.first = "one"; this.second = "two"; this.third = "three"; } //add the 'typing' object to our object A.prototype.myType = { firstType : function() { }, secondType : function() { //how do I alter the value of function A's "second" property from here? // 'this' is scoped to the current object }, thirdType : function() { } } B = new A(); var typeIt = "secondType"; if (typeIt in B.myType) { B.myType['typeIt']; } I want to change the value of A.second (well, once I invoke it as "B", it will be B.second) to be something other than "two." The 'this' keyword within A.myType references the myType object. How do I reference this instance of A, however? Thanks, in advance.
From: RobG on 15 Jul 2010 19:48 On Jul 16, 6:36 am, Jeremy <jerb...(a)gmail.com> wrote: > Hi, I'm trying to figure out how to modify the property of an object > from within an object descended from that parent object. Here's the > code: > > //new object > function A() { > this.first = "one"; > this.second = "two"; > this.third = "three"; > } When A is called as a constructor, its this keyword is set as a reference to a newly created object. Objects constructed using new A() (which might be called instances of A) will each have properties first, second and third with the values assigned above. > > //add the 'typing' object to our object > A.prototype.myType = { That doesn't add it to "our object", it creates a property called myType on A.prototype and assigns it a reference to a new object. Objects created from constructor A when it has this prototype object will inherit the myType property. > firstType : function() { > > }, > secondType : function() { > //how do I alter the value of function A's "second" property from > here? Function A doesn't have a "second" property, so it is impossible to modify it. It will create a "second" property of instances when called with the new keyword. What you have done is added a myType property to A.prototype and assigned it a reference to an object with a secondType property that is a function. To call it from an instance of A you'd need: a_Instance.myType.secondType() in which case, secondTypes's this keyword will be a reference to myType (because that's how it's called). The simple solution is to add the secondType function directly to A.prototype: A.prototype.secondType = function(){... A.prototype.thirdType = function(){... Alternatively, replace A.prototype with the myType object. Since the functions are setting values, I'd call them "set...": A.prototype = { setFirstType: function(value){ this.first = value; }, setSecondType: function(value){ this.second = value; }, setThirdType: function(value) { this.third = value; } }; Note that if you adopt the second approach, it will only affect instances of A created after the assignment. Instances created before then will use the previous A.prototype. > // 'this' is scoped to the current object The value of a function's this keyword has nothing to do with scope. Its value is completely under the control of the caller. > }, > thirdType : function() { > } > > } > > B = new A(); By convention, variable names starting with a capital letter are reserved for constructors and constants (which are usually all capitals). > var typeIt = "secondType"; > > if (typeIt in B.myType) { > B.myType['typeIt']; > } > > I want to change the value of A.second (well, once I invoke it as "B", > it will be B.second) There is no A.second, you want to change B.second. > to be something other than "two." The 'this' > keyword within A.myType references the myType object. How do I > reference this instance of A, however? There is no A.myType, nor is the myType property on A's prototype chain. Property resolution proceeds through the internal [[prototype]] property, which is (usually) a completely different set of objects to the public prototype property. Here's a full example: function A() { this.second = 'second'; } A.prototype = { setFirstType: function(value){ this.first = value; }, setSecondType: function(value){ this.second = value; }, setThirdType: function(value) { this.third = value; } }; var anA = new A(); alert(anA.second); // shows 'second' anA.setSecondType('new second type'); alert(anA.second); // shows 'new second type' Of course you are changing public properties of instances, next you'll want to know how to keep them private and only change them using privileged functions (getters and setters). That's been covered here too (and in various blogs). Come back when you're ready. :-) -- Rob
From: Thomas 'PointedEars' Lahn on 16 Jul 2010 10:10 RobG wrote: > Jeremy wrote: >> firstType : function() { >> >> }, >> secondType : function() { >> //how do I alter the value of function A's "second" >> property from >> here? > > Function A doesn't have a "second" property, so it is impossible to > modify it. It will create a "second" property of instances when called > with the new keyword. > > What you have done is added a myType property to A.prototype and > assigned it a reference to an object with a secondType property that > is a function. To call it from an instance of A you'd need: > > a_Instance.myType.secondType() > > in which case, secondTypes's this keyword will be a reference to > myType (because that's how it's called). The simple solution is to add > the secondType function directly to A.prototype: > > A.prototype.secondType = function(){... > A.prototype.thirdType = function(){... > > Alternatively, replace A.prototype with the myType object. Since the > functions are setting values, I'd call them "set...": > > A.prototype = { > setFirstType: function(value){ > this.first = value; > }, > setSecondType: function(value){ > this.second = value; > }, > setThirdType: function(value) { > this.third = value; > } > }; > > Note that if you adopt the second approach, it will only affect > instances of A created after the assignment. Instances created before > then will use the previous A.prototype. Further, since the value of the `prototype' property would be a reference to a newly created Object instance (through the Object initializer, `{'...`}'), the inherited `constructor' property of the latter instances would be `Object', not `A' anymore. This can be confusing. It is possible to add a corresponding user-defined `constructor' property to `A.prototype', but by contrast to the built-in `constructor' property it will be enumerable by default. ECMAScript Edition 5 specifies the Object.defineProperty() and Object.defineProperties() methods to define a non-enumerable property; they are implemented in Google V8 since version 2.1 (Chrome 5.0.342) and Apple JavaScriptCore since version 533.16 (Safari 4.0.4). As an alternative, the original prototype object can be kept and just augmented with properties. A way to do this is for-in iteration: var o = a_Instance.myType; for (var p in o) { A.prototype[p] = o[p]; } Note that a *shallow* copy of all *enumerable* properties, including inherited ones, of the object referred to by `o' will be created. If only own enumerable properties should be copied, the o.hasOwnProperty() method can be used. >> var typeIt = "secondType"; >> >> if (typeIt in B.myType) { >> B.myType['typeIt']; >> } >> >> I want to change the value of A.second (well, once I invoke it as "B", >> it will be B.second) > > There is no A.second, you want to change B.second. And remove the apostrophes around `typeIt', else the name of the accessed property would be `typeIt', not `secondType'. But it would still have no overly useful effect. PointedEars -- var bugRiddenCrashPronePieceOfJunk = ( navigator.userAgent.indexOf('MSIE 5') != -1 && navigator.userAgent.indexOf('Mac') != -1 ) // Plone, register_function.js:16
From: kangax on 16 Jul 2010 19:14 On 7/16/10 10:10 AM, Thomas 'PointedEars' Lahn wrote: > RobG wrote: [...] >> Note that if you adopt the second approach, it will only affect >> instances of A created after the assignment. Instances created before >> then will use the previous A.prototype. > > Further, since the value of the `prototype' property would be a reference to > a newly created Object instance (through the Object initializer, `{'...`}'), > the inherited `constructor' property of the latter instances would be > `Object', not `A' anymore. This can be confusing. It is possible to add a > corresponding user-defined `constructor' property to `A.prototype', but by > contrast to the built-in `constructor' property it will be enumerable by > default. ECMAScript Edition 5 specifies the Object.defineProperty() and > Object.defineProperties() methods to define a non-enumerable property; they > are implemented in Google V8 since version 2.1 (Chrome 5.0.342) and Apple > JavaScriptCore since version 533.16 (Safari 4.0.4). ^^^^^ That should be Safari 5, not 4.0.4 (build number is right, though). Also see <http://kangax.github.com/es5-compat-table/> [...] -- kangax
From: Thomas 'PointedEars' Lahn on 16 Jul 2010 19:31 kangax wrote: > Thomas 'PointedEars' Lahn wrote: >> RobG wrote: > [...] >> ECMAScript Edition 5 specifies the Object.defineProperty() and >> Object.defineProperties() methods to define a non-enumerable property; >> they are implemented in Google V8 since version 2.1 (Chrome 5.0.342) and >> Apple JavaScriptCore since version 533.16 (Safari 4.0.4). > ^^^^^ > > That should be Safari 5, not 4.0.4 (build number is right, though). > > Also see <http://kangax.github.com/es5-compat-table/> No. As a matter of fact, "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/533.16 (KHTML, like Gecko) Version/4.0.4 Safari/531.21.10" supports both Object.defineProperty() and Object.defineProperties(). PointedEars -- var bugRiddenCrashPronePieceOfJunk = ( navigator.userAgent.indexOf('MSIE 5') != -1 && navigator.userAgent.indexOf('Mac') != -1 ) // Plone, register_function.js:16
|
Next
|
Last
Pages: 1 2 Prev: Setter/Getter in module pattern? Next: FAQ Topic - What is JScript? (2010-07-16) |