From: Thomas 'PointedEars' Lahn on 17 Jan 2010 17:12 nick wrote: > | This standard specifies one departure from the grammar given in the > | Unicode standard: The dollar sign ($) and the underscore (_) are > | permitted anywhere in an identifier. The dollar sign is intended for > | use only in mechanically generated code. > > ... I didn't see where it recommended avoiding them, am I looking at > the wrong document? Your code is not mechanically generated, is it? AIUI, the reference to "mechanically generated" here is threefold: a) Code being generated by other code (e.g., server-side PHP generates ECMAScript-compliant code; to use `$' for a normal property would make the generating code harder to write and to read as variable references must start with `$' in, e.g., PHP). b) Built-in properties like $`; user-defined properties should be easily distinguishable from those. c) Host environments can augment native objects with properties; user-defined properties should be easily distinguishable from those. PointedEars -- Anyone who slaps a 'this page is best viewed with Browser X' label on a Web page appears to be yearning for the bad old days, before the Web, when you had very little chance of reading a document written on another computer, another word processor, or another network. -- Tim Berners-Lee
From: Thomas 'PointedEars' Lahn on 17 Jan 2010 17:47 nick wrote: > Thomas 'PointedEars' Lahn wrote: >> >> - You want to avoid augmenting Object.prototype. >> > >> > I'm not sure I do. How else will I be able to do things like this: >> > >> > var foo = document.body.style.$('backgroundcolor'); >> >> Bad inference. The `style' property of those objects does _not_ refer >> to a native object (but to a host object), so you cannot expect it to >> inherit from Object.prototype or be extensible. > > Sure, but it works in every browser I've tested it in, and not just > for 'style,' so it seems consistent and useful... As I said, bad inference. >> ... you are false assuming that an object can only ever be >> referred to by the same property, as your wrapper object has a property >> to store only that one property's name. > > I don't really see the problem here... even if the object is referred > to by other properties, my wrapper object only needs to know one way > to find it in order to modify and read its value. In other words, > > var bob = {name:'bob', age:33}; > var bobsDad = {son:bob, rel:'dad'}; > var bobsKid = {dad:bob, rel:'son'}; > > var p = bobsDad.son.$('age'); > p.$_(p + 10); Eeek. Compare that against bobsDad.son.age += 10; > alert (bobsKid.dad.age); // shows 43 You are really not making a good case here. >> The supposed-to-be type-cast `Object(this)' is also pointless because in >> the context in which it is used, `this' is already a reference to an >> object; or, IOW, `this' *always* refers to an object (for primitive >> values: due to the built-in wrapping object) and does not need to be >> type-casted (provided that was possible so easily). Incidentally, when >> the Object() function is called as a function or a constructor with an >> object reference as argument, it simply returns that reference without >> creating a new object (ES3/5, 15.2.1.1 and 15.2.2.1). > > I read that somewhere too, and originally I just had "return > this;" ... however it doesn't work in Google Chrome (beta 4 at least). Someone please file a bug after checking the released version. > Using the Object() function gives the expected result there. Simply > returning 'this' does seem to work in every other js implementation > I've seen. You probably mean "every other *ECMAScript* implementation" (Netscape/Mozilla.org JavaScript is one). >> > Using this would require rewriting all code, it just requires: (1) >> > wrap primitive in an object so you can use the $_() setter, and (2) >> > use the $_() setter to set a value when you want to modify the value >> > "by reference." >> >> And it would require rewriting of all functions and methods that used >> the wrapper object instead of the primitive value. Even though they >> only required read access. > > Wait, why? The wrapper object is treated as a primitive value by > anything that expects a primitive value. I stand corrected. Your example (`num.$_(num * num)') confused me. Still, obviously it would require rewriting all functions and methods that attempt to set the value. >> > Where did I modify constants? Not sure what you mean here either. >> >> `5' is a constant as is `"foo"'. Constant as in immutable. One would >> not attempt to modify immutable values, or emulate that by keeping a >> wrapper object to store another value. > > Yes, but [5] and ["foo"] are not constants ;) So what? If this was to be used on proper objects (like the Array instances here), it would have proven its own unnecessity. [5][0] === 5, ["foo"][0] === "foo". > What if you wanted to do something like this (perfectly valid c++): You don't. ECMAScript is not C++, Java is not PHP, Perl is not Python. Anyhow, no offense meant, but this code looks more like one from a C developer that failed to evolve from the need of direct memory manipulation than proper C++. > [...] > #include <stdio.h> > void square(int *n) { *n *= *n; } > int main() > { > int i = 5; > square(&i); > printf("%i\n",i); // prints 25 > return 0; This is even poor code quality by C standards. Pray tell, what is advantage of referring to a variable by reference only to discard it later? Is it not instead that the reference and ultimately the variable was unnecessary in the first place, that the function should have returned the proper value instead, as in int i = 5; printf("%i\n", i * i); or printf("%i\n", square(i)); or printf("%i\n", square(5)); or, $DEITY forbid, printf("%i\n", 5 * 5); or even printf("25\n"); ? > } > > ## ^^ Please do not do that. Use unambiguous delimiters like `---' or indent your code instead. > If I try to emulate that by doing something like the following, am I > really trying to modify constants? > > ## > > function square(n) { n._set(n * n); } > function main() > { > int i = [5]; What is this supposed to mean? (An Array instance that is a primitive integer -- a contradiction?) > square(i); In object-oriented programming, we have managed to move on beyond the context-less functions of the plain procedural programming paradigm that spoil the global namespace; instead, we try to associate functions with the data they are supposed to operate on, by which they become methods of the target object and work like (and sometimes are implemented as) messages to that object: i.square = function() { for (var i = this.length; i--;) { var v = this[i]; this[i] = v * v; } }; /* "square" `i' */ i.square(); Not that a method would be necessary here: for (var j = i.length; j--;) { var v = i[j]; i[j] = v * v; } (Kids, don't try this at home! `i' should be reserved for counters.) But it might come in handy. PointedEars -- Use any version of Microsoft Frontpage to create your site. (This won't prevent people from viewing your source, but no one will want to steal it.) -- from <http://www.vortex-webdesign.com/help/hidesource.htm> (404-comp.)
From: nick on 17 Jan 2010 18:42 On Jan 17, 5:47 pm, Thomas 'PointedEars' Lahn <PointedE...(a)web.de> wrote: > >> ... you are false assuming that an object can only ever be > >> referred to by the same property, as your wrapper object has a property > >> to store only that one property's name. > > > I don't really see the problem here... even if the object is referred > > to by other properties, my wrapper object only needs to know one way > > to find it in order to modify and read its value. In other words, > > > var bob = {name:'bob', age:33}; > > var bobsDad = {son:bob, rel:'dad'}; > > var bobsKid = {dad:bob, rel:'son'}; > > > var p = bobsDad.son.$('age'); > > p.$_(p + 10); > > Eeek. Compare that against > > bobsDad.son.age += 10; > > > alert (bobsKid.dad.age); // shows 43 > > You are really not making a good case here. > The point I was trying to make was I am not "assuming that an object can only ever be referred to by the same property" ... I'm assuming it doesn't matter. Can you think of an example where this would be a problem? > > >> > Where did I modify constants? Not sure what you mean here either. > > >> `5' is a constant as is `"foo"'. Constant as in immutable. One would > >> not attempt to modify immutable values, or emulate that by keeping a > >> wrapper object to store another value. > > > Yes, but [5] and ["foo"] are not constants ;) > > So what? If this was to be used on proper objects (like the Array > instances here), it would have proven its own unnecessity. [5][0] === 5, > ["foo"][0] === "foo". What? Regular objects are already passed by reference, I'm not worried about that. I want to reference primitive types. > > [...] > > #include <stdio.h> > > void square(int *n) { *n *= *n; } > > int main() > > { > > int i = 5; > > square(&i); > > printf("%i\n",i); // prints 25 > > return 0; > > This is even poor code quality by C standards. Pray tell, what is > advantage of referring to a variable by reference only to discard it later? > Is it not instead that the reference and ultimately the variable was > unnecessary in the first place, that the function should have returned the > proper value instead, as in > > int i = 5; > printf("%i\n", i * i); > > or > > printf("%i\n", square(i)); > > or > > printf("%i\n", square(5)); > > or, $DEITY forbid, > > printf("%i\n", 5 * 5); > > or even > > printf("25\n"); > > ? > It's just example code that I typed up in 5 seconds, the point is that I'm passing integers by reference. Obviously there is no "advantage" to anything I did in this scenario... it's just a simple example. > > } > > > ## > > ^^ > Please do not do that. Use unambiguous delimiters like `---' or indent > your code instead. > Whatever makes you happy. `---' > > If I try to emulate that by doing something like the following, am I > > really trying to modify constants? > > > ## > > > function square(n) { n._set(n * n); } > > function main() > > { > > int i = [5]; > > What is this supposed to mean? (An Array instance that is a primitive > integer -- a contradiction?) > `---' The [5] notation is just for wrapping a primitive in an an object, like Object(5). `---' > > square(i); > > In object-oriented programming, we have managed to move on beyond the > context-less functions of the plain procedural programming paradigm that > spoil the global namespace; instead, we try to associate functions with the > data they are supposed to operate on, by which they become methods of the > target object and work like (and sometimes are implemented as) messages to > that object: > ... > (Kids, don't try this at home! `i' should be reserved for counters.) `---' Look, I don't need a lecture on object-oriented programming (js not being an OO language last time I checked anyway). There is plenty of C+ + code around where classes have methods that pass and receive pointers to ints and doubles all over the place... FLTK comes to mind. Whether or not you think passing primitive types by reference in an OO language is a good idea, it's useful, it's fast and it works. /OT Whether or not that translates to *ECMAScript* I can't say, but it is at least a fun learning experiment :) -- Nick
From: Thomas 'PointedEars' Lahn on 17 Jan 2010 19:32 nick wrote: > Thomas 'PointedEars' Lahn wrote: >> >> ... you are false assuming that an object can only ever be >> >> referred to by the same property, as your wrapper object has a >> >> property to store only that one property's name. >> > >> > I don't really see the problem here... even if the object is referred >> > to by other properties, my wrapper object only needs to know one way >> > to find it in order to modify and read its value. In other words, >> > >> > var bob = {name:'bob', age:33}; >> > var bobsDad = {son:bob, rel:'dad'}; >> > var bobsKid = {dad:bob, rel:'son'}; >> > >> > var p = bobsDad.son.$('age'); >> > p.$_(p + 10); >> >> Eeek. Compare that against >> >> bobsDad.son.age += 10; >> >> > alert (bobsKid.dad.age); // shows 43 >> >> You are really not making a good case here. > > The point I was trying to make was I am not "assuming that an object > can only ever be referred to by the same property" ... I'm assuming it > doesn't matter. Can you think of an example where this would be a > problem? The `$' aside? Perhaps. I need to think about it, later. >> >> > Where did I modify constants? Not sure what you mean here either. >> >> >> >> `5' is a constant as is `"foo"'. Constant as in immutable. One >> >> would not attempt to modify immutable values, or emulate that by >> >> keeping a wrapper object to store another value. >> > >> > Yes, but [5] and ["foo"] are not constants ;) >> >> So what? If this was to be used on proper objects (like the Array >> instances here), it would have proven its own unnecessity. [5][0] === >> 5, ["foo"][0] === "foo". > > What? Regular objects are already passed by reference, No, objects are not passed at all. Object *references*, which are values, are passed by value, like everything else. > I'm not worried about that. I want to reference primitive types. Do not use proper objects as examples to make a point, then. >> > [...] >> > #include <stdio.h> >> > void square(int *n) { *n *= *n; } >> > int main() >> > { >> > int i = 5; >> > square(&i); >> > printf("%i\n",i); // prints 25 >> > return 0; >> >> This is even poor code quality by C standards. Pray tell, what is >> advantage of referring to a variable by reference only to discard it >> later? Is it not instead that the reference and ultimately the variable >> was unnecessary in the first place, that the function should have >> returned the proper value instead, as in [counter-examples]? > > It's just example code that I typed up in 5 seconds, the point is that > I'm passing integers by reference. Obviously there is no "advantage" > to anything I did in this scenario... it's just a simple example. A simple example that shows why this approach does not make sense, that it is the result of a misconception. >> > } >> >> > ## >> >> ^^ >> Please do not do that. Use unambiguous delimiters like `---' or indent >> your code instead. > > Whatever makes you happy. > > `---' First of all, this is not about me. Second, the <`> and <'> only delimit the suggested string of characters, of course. Third, it was supposed to delimit source code from comments, not everything from each other. This is Usenet; learn to post. [snipped bogus delimiters] >> > If I try to emulate that by doing something like the following, am I >> > really trying to modify constants? >> > >> > function square(n) { n._set(n * n); } >> > function main() >> > { >> > int i = [5]; >> >> What is this supposed to mean? (An Array instance that is a primitive >> integer -- a contradiction?) > > The [5] notation is just for wrapping a primitive in an an object, > like Object(5). Object(5) is unnecessary, though. Wrapper objects that have the corresponding prototype objects in their prototype chain are created automatically whenever primitive convertible values are used with property accessors. >> > square(i); >> >> In object-oriented programming, we have managed to move on beyond the >> context-less functions of the plain procedural programming paradigm that >> spoil the global namespace; instead, we try to associate functions with >> the data they are supposed to operate on, by which they become methods >> of the target object and work like (and sometimes are implemented as) >> messages to that object: [...] > > Look, I don't need a lecture on object-oriented programming Quite obviously you do. > (js not being an OO language last time I checked anyway). Check again. > Whether or not that translates to ECMAScript I can't say, but it is > at least a fun learning experiment :) Undoubtedly. However, I do not think you have learned all the right lessons from it (yet). PointedEars -- var bugRiddenCrashPronePieceOfJunk = ( navigator.userAgent.indexOf('MSIE 5') != -1 && navigator.userAgent.indexOf('Mac') != -1 ) // Plone, register_function.js:16
From: nick on 17 Jan 2010 20:24 On Jan 17, 7:32 pm, Thomas 'PointedEars' Lahn <PointedE...(a)web.de> wrote: > nick wrote: > ... > > What? Regular objects are already passed by reference, > > No, objects are not passed at all. Object *references*, which are values, > are passed by value, like everything else. > Semantics. I think my meaning was clear. > > Object(5) is unnecessary, though. Wrapper objects that have the > corresponding prototype objects in their prototype chain are created > automatically whenever primitive convertible values are used with property > accessors. > Right, but writing "var foo=5;" is not the same as "var foo=Object (5);" In other words, "var foo=5" is like "var foo=Number(5)", while "var foo=Object(5);" acts like "var foo=new Number(5);" would... even though both get automatically wrapped by a wrapper object, in the first case foo is assigned the primitive value, instead of the reference to the wrapper object. In other words the automatic wrappers seem "temporary," while objects created with {}, [], Object(), seem to "stick around." I'm sure that is horribly semantically incorrect, though. Look: --- // Set the value of current object. Number.prototype._set = function(value) { var v = value.valueOf(); this.valueOf = this.toString = function() { return v; }; return this; }; function square(num) { num._set( num * num ); } var x = 5; square(x); alert(x); // gives 5 -- no good var y = new Number(5); square(y); alert(y); // gives 25 -- yay var z = Object(5); square(z); alert(z); // gives 25 -- this works too --- > > > Look, I don't need a lecture on object-oriented programming > > Quite obviously you do. > Excuse me but I can't imagine why you think that. Is it because my 5- line example code has no real world use, or because you really think references to primitive types have no place in OO programming? Either way, I'll try to give a better example. In a UI toolkit, a spinner control class has a property called "Value." Value is a pointer to an int. Another class (call it Box) has two properties, Top and Left, both pointers to ints. During the display routine, Box will draw itself according to Top and Left. The spinner control will show "Value" in a text box. Now, say vSpinner.Value and myBox.Top point at the same int, and hSpinner.Value and myBox.Left point at the same value... and lets say you can drag Box around, which will modify its Top and Left properties. Spinning the spinners will now move the box, moving the box will update the spinners, and everything is kept in sync. There you have it, useful pointers to primitive types in OOP. I hope that example helps? -- Nick
First
|
Prev
|
Next
|
Last
Pages: 1 2 3 4 Prev: knowing what and when to feature test Next: iscontenteditable browser support |