Path: csiph.com!news.mixmin.net!weretis.net!feeder1.news.weretis.net!news.solani.org!.POSTED!not-for-mail From: Thomas 'PointedEars' Lahn Newsgroups: comp.lang.javascript Subject: Re: Refer object within itself Date: Fri, 26 Feb 2016 19:23:26 +0100 Organization: PointedEars Software (PES) Lines: 154 Message-ID: <10425603.zxHOPjekVl@PointedEars.de> References: <76ydnVazm-uPoU3LnZ2dnUU7-TGdnZ2d@westnet.com.au> Reply-To: Thomas 'PointedEars' Lahn Mime-Version: 1.0 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: 8Bit X-Trace: solani.org 1456511007 11263 eJwFwQkBACAIA8BK8mxgHFDpH8E7GIUnnKBjMHu36yghnax0b5jPkxUPaTdWVwXqCk6ODj8MfBDZ (26 Feb 2016 18:23:27 GMT) X-Complaints-To: abuse@news.solani.org NNTP-Posting-Date: Fri, 26 Feb 2016 18:23:27 +0000 (UTC) User-Agent: KNode/4.14.2 X-User-ID: eJwVxskNADEIA8CWuOyQcgKC/ktY7bwGTmWfIBhYLLM09J45lrlCqSjuPIZrdedgGxLdNn9M+0HumirGq+4HSdYVhw== Cancel-Lock: sha1:U3YovythX6UnmgHRkCxkPl+tfXU= X-NNTP-Posting-Host: eJwFwQEBACAIA7BKov5IHEDfP4IbFo3tm+CGIEO9pR63dXDH8xnVURWeRjfxMCeAlFWg9gcuAhFp Xref: csiph.com comp.lang.javascript:29709 Andrew Poulos wrote: > Say I have this object > > var foo { ^ > "name":"bar" > "width":600 > } > > and I want to add another element that references a value within the > object itself. eg > > var foo { ^ > "name":"bar" > "width":600, > "height": width * 2 > } > > Both > "height": this.width * 2 > and > "height": foo.width * 2 > > return errors or undefined. They do because “width” has to be resolved *before* the object is constructed and a reference to it is assigned to “foo” (had you used the assignment operator). Keep in mind that the above (if written correctly) is functionally equivalent to: var o = new Object(); o.name = "bar"; o.width = 600; /* or this.width or foo.width, respectively */ o.height = width * 2; foo = o; > How do I reference to the object itself within the object? The reason that your approach does not work is that you are _not_ “within the object” there. > Or should it be done line this > > var foo { ^ > "name":"bar" > "width":600 > } > foo.height = foo.width * 2; Certainly not, as that would be a syntax error as well ;-) You can write it thus: var foo = (function () { var width = 600; return { name: "bar" width: width, height: width * 2 }; }()); That is not necessarily what you want, because the value of the “height” property is then not *bound* to the value of the “width” property of the same object: if the “width” property value changes, the “height” property value does not change with it. Without Proxy (ECMAScript 2015+) – see Stefan Ram’s answer –, you can define this relationship in a more compatible way using a getter (ECMAScript Ed. 5+): var foo = Object.create(Object.prototype, { name: { value: "bar", configurable: true, enumerable: true, writable: true }, width: { value: 600, configurable: true, enumerable: true, writable: true }, height: { "get": function () { return this.width * 2; }, configurable: true, enumerable: true } }); or, less explicit: var foo = Object.defineProperty( { name: "bar", width: 600 }, "height", { "get": function () { return this.width * 2; }, configurable: true, enumerable: true } ); (Getters and Setters have been supported in various ways even before ECMAScript Ed. 5; see JSX:object.js for a wrapper implementation.) You can use “null” instead of “Object.prototype” if you do not want your object to inherit any properties, and you can omit definitions for the “configurable”, “enumerable”, and “writable” properties if you want the property to be not configurable, enumerable, or writable, respectively. Note that such an accessor property with only a getter is read-only, until you reconfigure it (which is only possible if it is also configurable) to have a setter (in which case the new getter needs to return, and the new setter needs to write a value of another property or variable), or to have a value instead (in which case it also should be defined as writable). Therefore, another alternative is var foo = (function () { var width = 600; return Object.defineProperties({name: "bar"}, { width: { "get": function () { return width; }, "set": function (value) { width = value; }, configurable: true, enumerable: true }, height: { "get": function () { return width * 2; }, configurable: true, enumerable: true } }); }()); -- PointedEars FAQ: | SVN: Twitter: @PointedEars2 | ES Matrix: Please do not cc me. / Bitte keine Kopien per E-Mail.