Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Results 1 to 14 of 14
  1. #1
    Senior Coder rnd me's Avatar
    Join Date
    Jun 2007
    Location
    Urbana
    Posts
    4,371
    Thanks
    11
    Thanked 591 Times in 572 Posts

    Post custom javascript keywords

    problem
    One annoying part of javascript is the almost-array arguments object.
    because it does have the nice Array methods like sort(), slice(), map(), etc, it's not nearly as powerful as it could be.
    This is a known problem, and the next version of javascript, ECMA 6, sets out to fix this using "rest parameters".

    You can actually use these today in firefox.

    Still, it would be nice if we could use these today (on real projects) so we can avoid pounding out the slice wrapper 15 million times each project:
    Code:
    [].slice.call(arguments)
    or if haven't met mr RSI yet :
    Code:
    Array.prototype.slice.call(arguments)
    I've posted stand-alone functions that convert an almmost-array (iterable) into an array:

    Code:
    var toArray=Function.call.bind([].slice);
    but that's still a wrapper and a lot to type (22 key presses) :
    Code:
    toArray(arguments)

    what if we can type 4 keys and do the same thing? :
    Code:
    args

    turns out, we can. now at least. booya!

    solution
    This is accomplished using Object.defineProperty(), which works in IE8+.
    The code below adds a few new keywords to javascript.


    • args - a true array of the arguments passed to a function
    • me - the current function you are in, same as arguments.callee witout the typing
    • caller - the powerhouse - a function that called the function you are in (sadly not linked in IE8, but it works in IE9 and everywhere else)
    • params - a true gem - equals an object with the keys of the formal parameters and the values of the arguments. it can make one-line constructors.



    that's right, we can add new keywords smack dab into the middle of functions. How is this possible?

    1. Using getters, we can make a function act like a property.
    2. Using a function, we can see what's going on around the function.
    3. By making a few global methods that act like properties, we get global methods that need no arguments: keywords!


    I'll mention again that all of these except caller work in IE8, along with even not-so-recent copies Firefox, and Webkit.


    The Keyword Adding Code
    Code:
    // custom keyword adder (me, caller, args, params) (PUBLIC DOMAIN BY AUTHOR)
    (function defKeywords() {
    	(function def(key, fn) {
    		if (!self[key]) {
    			Object.defineProperty(self, key, {
    				get: fn
    			});
    		}
    		return def;
    
    	})("args", function _args() {
    		return [].slice.call(arguments.callee.caller.arguments);
    
    
    	})("caller", function _caller() { // note: caller is N/A in IE8 (null), works in IE9+
    		return arguments.callee.caller.arguments.callee.caller;
    
    
    	})("params", function _params() {
    		var src = arguments.callee.caller,
    			params = {};
    		var keys = src.toString().split("(")[1].split(")")[0].match(/[\w\$]+/g) || [];
    		for (var i = 0, mx = keys.length; i < mx; i++) {
    			params[keys[i]] = src.arguments[i];
    		}
    		return params;
    
    	})("me", function _me() {
    		return arguments.callee.caller;
    	});
    }()); //end keyword wrapper()



    compressed code (less than half a KB)
    Code:
    //keyword defs: args, me, caller, params (PUBLIC DOMAIN BY AUTHOR)
    (function(){var D="caller",A="callee",B=D,C="arguments";(function b(a,c){return self[a]||Object.defineProperty(self,a,{get:c}),b})("args",function(){
    return[].slice.call(arguments[A][B][C])})(D,function(){return arguments[A][B][C][A][B]})("params",function(){for(var b=arguments[A][B],a={},
    c=b.toString().split("(")[1].split(")")[0].match(/[\w\$]+/g)||[],d=0,e=c.length;d<e;d++)a[c[d]]=b[C][d];return a})("me",function(){return arguments[A][B]})})();
    //end keyword wrapper()

    you can rename the keywords if you think "me" or "args" will clash with code you've written before, just change the quoted method name in the definition.
    the all-in-one adder won't step on any existing globals, so it won't break existing code, but it won't work as documented either...


    if you don't want the whole bundle, or are confused by the space-saving injector, you can use these stand-alone keyword definitions willy-nilly:

    Stand-Alone Versions of each keyword

    Code:
    Object.defineProperty(self, "args", {
    	get: function _args() {
    		return [].slice.call(arguments.callee.caller.arguments);
    	}
    });
    
    Object.defineProperty(self, "me", {
    	get: function _me() {
    		return arguments.callee.caller;
    	} 
    });
    
    
    Object.defineProperty(self, "caller", {
    	get: function _caller() {
    		return arguments.callee.caller.arguments.callee.caller;
    	} 
    });
    
    Object.defineProperty(self, "params", {
    	get: function _params() {
    		var src=arguments.callee.caller,   params={};
    		var keys=src.toString().split("(")[1].split(")")[0].match(/[\w\$]+/g)||[];
    		for(var i=0, mx=keys.length;i<mx;i++){   
    			params[keys[i]]=src.arguments[i];
    		}
    		return params;
    	} 
    });


    demo usage examples (tested IE8, IE9, IE10, FF, Ch)
    Code:
    function viewer(obj){ //just for these demo example, not really needed
     alert( typeof obj=='object'?JSON.stringify(obj, null, "\t") : obj );
    }
    
    
    function testArgs(){
     viewer(args);
    }
    testArgs(1,2,3); //== [1,2,3]
    
    
    function testParams(a,b,c){
     viewer(params);
    }
    testParams(1,2,3); //== {a:1, b:2, c:3}
    
    
    
    function testMe(){
     viewer(me);
    }
    testMe(); // ==  testMe(){ viewer(me);}
    
    
    
    function testCallerInternal(){
      viewer(caller);
    }
    function testCaller(){
       testCallerInternal()
    }
    testCaller() //== function testCaller(){testCallerInternal()} 
     // note in IE8 this shows testCallerInternal instead of testCaller


    what about that one-line constructor i promised?
    Code:
    function person(age, sex, location){ return params; }
    
    view(
      person(23, "male", 90210)
    );
    which shows:
    Code:
    {
    	"age": 23,
    	"sex": "male",
    	"location": 90210
    }



    This "custom keyword" pattern can be used for other things as well, the extent of which i'm not quite sure.
    If you can think up any cool uses, please post them in a reply.
    Anything you can do in a no-arguments-passed Function prototype method, you should be able to do as a keyword.


    the custom keyword idea has been laying dormant for five years, i'm really intrigued by what all could be accomplished using the concept.

    Please share!
    my site (updated 13/9/26)
    BROWSER STATS [% share] (2014/9/03) IE7:0.1, IE8:4.6, IE11:9.1, IE9:3.1, IE10:3.0, FF:17.2, CH:46, SF:11.4, NON-MOUSE:38%

  • #2
    Master Coder felgall's Avatar
    Join Date
    Sep 2005
    Location
    Sydney, Australia
    Posts
    6,642
    Thanks
    0
    Thanked 649 Times in 639 Posts
    Those would be really useful if it weren't that ECMAScript 5 did away with caller and callee so that none of the versions you listed will work if your script uses "use strict". Do you have any thoughts on how to do it now that those commands no longer exist?

    Running your code produces the following error at the point where it tries to access the now invalid callee property.

    Code:
    Uncaught exception: TypeError: Illegal property access
    Error thrown at line 14, column 2 in _args() in file://localhost/testjs.htm:
        return [].slice.call(arguments.callee.caller.arguments);
    called from line 41, column 1 in testArgs() in file://localhost/testjs.htm:
        viewer(args);
    called from line 43, column 0 in file://localhost/testjs.htm:
        testArgs(1,2,3);
    ps. it does work fine if you revert back to using the pre 2011 version of JavaScript.
    Last edited by felgall; 02-23-2013 at 10:40 PM.
    Stephen
    Learn Modern JavaScript - http://javascriptexample.net/
    Helping others to solve their computer problem at http://www.felgall.com/

    Don't forget to start your JavaScript code with "use strict"; which makes it easier to find errors in your code.

  • #3
    Senior Coder rnd me's Avatar
    Join Date
    Jun 2007
    Location
    Urbana
    Posts
    4,371
    Thanks
    11
    Thanked 591 Times in 572 Posts
    Quote Originally Posted by felgall View Post
    Those would be really useful if it weren't that ECMAScript 5 did away with caller and callee so that none of the versions you listed will work if your script uses "use strict". Do you have any thoughts on how to do it now that those commands no longer exist?
    that should only be a problem if you use the functionality-reduced "use strict" token globally, which you should not do in production at this point.

    it's advised for compatibility and performance reasons to only "use strict" inside of functions. Obviously, if your function itself uses the "use strict" sub-set, these won't work. You should be able to call them

    I strongly disagree that something is only "really useful" if it works in "use strict", after all, most code doesn't. "use strict" is not a desirable production feature, it's a limited subset of javascript capability. It can, like jslint, help enforce good coding practices in the development stage, but at least at this point, it's not without risk to use it in production-level code.


    i've never heard of someone complaining that something won't work in ES3 CP, so why is "use strict" seemingly put on a pedestal?

    it's not the case that this is a compatibility issue; no browser only runs strict code, many run it slower, and some pay no attention to the statement at all.

    in summary, since "use strict" code is not as powerful/flexible as normal code, you're going to have to use the old-fashioned wrappers and type out "arguments", or find-and-replace away the "use strict" statements and call it a day.


    EDIT:
    that's not to say that the custom keyword concept in general won't work with "use strict", only that these particular methods themselves break down under those conditions.

    for example, i thought of another one called NOW, which should be ok under "use strict":
    Code:
    Object.defineProperty(self, "NOW", {
    	get: function _me() {
    		return + new Date;
    	} 
    });
    this lets NOW act like a constant that indicates the current unix time.



    edit2:
    you can still use "use strict" in your code, even with these new keywords, as long as you don't use "use strict" in the outer function that uses the keywords.
    if i used in say, a constructor, i could still go "use strict" in all my methods, using the constructor to simply bind all those up into an object.
    that way, the critical parts of the code can validate under "use strict", and you can still code cleaner constructors using the new keywords.
    Last edited by rnd me; 02-24-2013 at 12:02 AM.
    my site (updated 13/9/26)
    BROWSER STATS [% share] (2014/9/03) IE7:0.1, IE8:4.6, IE11:9.1, IE9:3.1, IE10:3.0, FF:17.2, CH:46, SF:11.4, NON-MOUSE:38%

  • #4
    Master Coder felgall's Avatar
    Join Date
    Sep 2005
    Location
    Sydney, Australia
    Posts
    6,642
    Thanks
    0
    Thanked 649 Times in 639 Posts
    Quote Originally Posted by rnd me View Post
    that should only be a problem if you use the functionality-reduced "use strict" token globally, which you should not do in production at this point.
    Why not? It has been the standard since 2011. Code that doesn't work without "use strict" is using the old version of JavaScript that the 2011 version replaced.

    That "use strict" was introduced at all was simply to allow all the antiquated scripts written to the old standard to continue to work. All scripts written since 2011 should be written to the new standard which means using "use strict" to identify that the script was written to the standard that has applied since 2011.

    Code that uses "use strict" is not using a subset of JavaScript. Those commands that it doesn't support were declared to be obsolete in 2011 and are now only supported so that antiquated scripts that use them do not break.

    What you shouldn't be doing whether you actually specify "use strict" or not is to use obsolete commands such as callee in new scripts. Those commands are no longer a part of the current version of JavaScript in the same way the font tag is no longer a part of HTML.

    Regardless of whether you have "use strict" or not - callee ceased to be a JavaScript command in 2011.


    "use strict" does two things - with the few commands where the implementation has changed (eg. eval) it identifies whether the current or obsolete meaning of the command is to be used and it identifies where you have used obsolete commands that are no longer a part of JavaScript and refuses to run them.

    With the exception of where the meaning of commands you are using has changed it shouldn't matter whether you have "use strict" in your code or not - if your code is written to follow the JavaScript standards then adding it to a script that doesn't already have it should make no difference. If it does then the script either uses commands that now work differently or you are using commands that are no longer valid in JavaScript.
    Last edited by felgall; 02-24-2013 at 06:37 PM.
    Stephen
    Learn Modern JavaScript - http://javascriptexample.net/
    Helping others to solve their computer problem at http://www.felgall.com/

    Don't forget to start your JavaScript code with "use strict"; which makes it easier to find errors in your code.

  • #5
    Senior Coder rnd me's Avatar
    Join Date
    Jun 2007
    Location
    Urbana
    Posts
    4,371
    Thanks
    11
    Thanked 591 Times in 572 Posts
    Quote Originally Posted by felgall View Post
    Why not? It has been the standard since 2011. Code that doesn't work without "use strict" is using the old version of JavaScript that the 2011 version replaced.
    use strict is the same age as other ecmaScript. You are the only one who thinks it's newer than regular ecmaScript. It was not made to replace the full set, it was made to provide another option.
    think of it like XHTML, there were transitional, frameset, and strict versions. You wouldn't claim that transitional can't use the attribs that strict removed, they are different doctypes! Just like "use strict", xhtml strict removed some problematic and some actually useful features. That's probably why many of the removed features in xhtml strict re-appeared in html5. Ecma could have thrown arguments.callee to the curb in 6, but they haven't. I guess they think it's still of use, there's no other reason to leave it in...

    would you claim that since xhtml strict does away with some of transitional's valid attribs that anyone using a transitional doctype is running obsolete code?

    Quote Originally Posted by felgall View Post

    That "use strict" was introduced at all was simply to allow all the antiquated scripts written to the old standard to continue to work. All scripts written since 2011 should be written to the new standard which means using "use strict" to identify that the script was written to the standard that has applied since 2011.
    can you show me any old script that works with "use strict", but not without it? It;s not quirks mode, it's a easier-to-compile subset of the full language features. Just one will do. You've failed to offer any known examples, instead projecting only dramatic claims with no substantiation.

    Quote Originally Posted by felgall View Post
    Code that uses "use strict" is not using a subset of JavaScript. Those commands that it doesn't support were declared to be obsolete in 2011 and are now only supported so that antiquated scripts that use them do not break.


    A subset is where you have less of the same thing as something else. Most the the strict subset is the same as full JS. there a few minor errors checking diffs of limited value, but you don't get all the commands of the full language. When you have most of all, and what you have is the same as the stuff in the all, you have a subset. that's just math, not opinion.



    Quote Originally Posted by felgall View Post
    What you shouldn't be doing whether you actually specify "use strict" or not is to use obsolete commands such as callee in new scripts. Those commands are no longer a part of the current version of JavaScript in the same way the font tag is no longer a part of HTML.

    Regardless of whether you have "use strict" or not - callee ceased to be a JavaScript command in 2011.
    ...

    If it does then the script either uses commands that now work differently or you are using commands that are no longer valid in JavaScript.
    Really? not a standard huh? why o why is callee spec'd in ecma5 and more over, why is it STILL spec'd in ecma6? ecma6 is after 2011, and guess what? argument.callee still there! Not a standard? Hmm. Well, most (all) of the other commands in the standard are standards; that's what specs are...

    aside, can you name a single browser that only runs strict?

    you're misunderstanding of "use strict" is vast, surprising, and regrettable. Usually your advice is right on, even if a little heavy-handed. But this, you're banging a war drum for a battle that's not to be.

    obsolete? not standard? deprecated? settle down, the code works fine.

    If you don't want to use the handy code because of some self-imposed personal beliefs, fine, don't use it. But, I put a lot of work into this and i don't need you trashing my effort for some arbitrary condition that only seems to matter to you. If it were an old IE point, at leasst that has several milion users the script leaves behind. There's no issue like that here, everything is working just fine to all except you.

    If you don't have anything nice to say...

    believe me, understand what you are saying, and frankly, it's not helping. I know what you mean, no more details required. I'll ask you politely refrain from posting further non-constructive comments about this. please and thank you.
    Last edited by rnd me; 02-24-2013 at 08:42 PM.
    my site (updated 13/9/26)
    BROWSER STATS [% share] (2014/9/03) IE7:0.1, IE8:4.6, IE11:9.1, IE9:3.1, IE10:3.0, FF:17.2, CH:46, SF:11.4, NON-MOUSE:38%

  • #6
    Master Coder felgall's Avatar
    Join Date
    Sep 2005
    Location
    Sydney, Australia
    Posts
    6,642
    Thanks
    0
    Thanked 649 Times in 639 Posts
    Quote Originally Posted by rnd me View Post
    think of it like XHTML, there were transitional, frameset, and strict versions.
    That's exactly what it is like.

    In (X)HTML the strict doctype is there for people using only HTML 4 (or XHTML 1.0). The other two doctypes are for pages that are still transitioning from HTML 3.2 and which still use some of the long obsolete HTML 3.2 tags that were removed from HTML in 1997.

    Similarly with JavaScript a number of unnecessary and problematic commands were removed from the language in 2011 but as a lot of scripts still use those now obsolete commands the "use strict" command was introduced to make it easier to test whether your code is using obsolete commands.


    All new (X)HTML should be written using a strict doctype and all new JavaScript should be written so that it can work with "use strict". In both cases the other alternative is for old pages that are yet to be updated to follow the latest standard.

    That most web pages still use HTML 3.2 even though HTML 4 has been the standard for over 15 years is because a lot of people do not understand that the transitional doctype is there for web pages that are transitioning from the long dead HTML 3.2 to the new HTML 4 standard.

    With JavaScript the commands no longer recognised if you use "use strict" are those which the standards body have agreed should never have been a part of the language in the first place. Most would argue that they didn't go far enough but there then there is another round of changes to further fix the language that are intended to be released once more people stop using those commands that have now been removed (and which more experienced JavaScript programmers stopped using many years ago).

    A web page using an HTML 4 transitional doctype might still be using HTML 3.2 and is supposed to be in the process of being rewritten to get rid of those tags deleted from HTML 4. A script that doesn't have "use strict" might or might not be using the poorly thought out JavaScript commands that were originally introduced in JavaScript and which were deleted in ECMAScript 5, but if you add "use script" and it still works in browsers that support that directive then you know that it complies with the latest standard and is not using obsolete code.


    The current (X)HTML standard uses a strict doctype as pages written for HTML4/XHTML1.0 should not be written using HTML3.2 tags. The current JavaScript standard can use the "use strict" directive because pages written for EXCMAScript 5 should not be ECMAScript 3 commands that are no longer a part of JavaScript but which are now supported simply to avoid breaking all the antiquated scripts that still use them. The reason callee is included in ECMAScript 5 & 6 is as a deprecated command for backwards support for older scripts that still use it. Having seen that most of the web is still written using HTML 3.2 tags those looking after the JavaScript standards don't expect all of the now obsolete JavaScript commands to disappear all that quickly either - especially when some people appear to be assuming that the new version of JavaScript is a subset when in fact it still contains unnecessary commands that are still valid but which shouldn't be used.


    Anyway, you still haven't responded to the question I asked in my first post on this thread. I agree that what you are trying to do here is a good idea. Do you have any thoughts on how to implement it without using commands that were removed from JavaScript back in 2011?
    Last edited by felgall; 02-24-2013 at 09:13 PM.
    Stephen
    Learn Modern JavaScript - http://javascriptexample.net/
    Helping others to solve their computer problem at http://www.felgall.com/

    Don't forget to start your JavaScript code with "use strict"; which makes it easier to find errors in your code.

  • #7
    Senior Coder rnd me's Avatar
    Join Date
    Jun 2007
    Location
    Urbana
    Posts
    4,371
    Thanks
    11
    Thanked 591 Times in 572 Posts
    Quote Originally Posted by felgall View Post
    The current (X)HTML standard uses a strict doctype as pages written for HTML4/XHTML1.0 should not be written using HTML3.2 tags. The current JavaScript standard can use the "use strict" directive because pages written for EXCMAScript 5 should not be ECMAScript 3 commands that are no longer a part of JavaScript but which are now supported simply to avoid breaking all the antiquated scripts that still use them. The reason callee is included in ECMAScript 5 & 6 is as a deprecated command for backwards support for older scripts that still use it. Having seen that most of the web is still written using HTML 3.2 tags those looking after the JavaScript standards don't expect all of the now obsolete JavaScript commands to disappear all that quickly either - especially when some people appear to be assuming that the new version of JavaScript is a subset when in fact it still contains unnecessary commands that are still valid but which shouldn't be used.

    heh; my point was actually what we should be using HTML5 now...
    many of the "deprecated" stuff in xhtml trans that was removed in xhtml strict is back in html5, by popular demand. that's my point.
    i remember back in 2008 people were mocking html5 saying stuff like "html5, wow that's great if i don't mind waiting until 2013 to write my site"... Well even those slow adopters who follow the crowd instead of leading it have switched over, since it is five years later and compliance is about 9/10 clients. It's probably still not even an "According to Hoyle" standard, but that's not going to stop anyone from using it this afternoon.


    i believe you are making a valid de jure philosophical argument, whereas my assumptions are more de facto and pragmatic...


    "still valid but which shouldn't be used" ? wtf? why not? that doesn't make a whole lot of sense does it? anyone who's been in web development for a while knows the discrepancy between card-shuffling on a standards committee and what actually works in the here and now. That's a good thing: it gave us innerHTML, ajax, localStorage, JSON, [].map(), and many other useful now-standardized features.

    i'll go so far as to agree that arguments.callee is deprecated, but that doesn't mean it's not present and operational. Furthermore, the soonest opportunity to turn it off will be with the release and uptake of ECMA7. I think it's fair to say that's at least five years away. Meanwhile this works right now, in all semi-recent and future browsers. Both "use strict" and full JS work in all browsers, they are both there, and nothing is on the verge of disappearing.


    Quote Originally Posted by felgall View Post
    Anyway, you still haven't responded to the question I asked in my first post on this thread. I agree that what you are trying to do here is a good idea. Do you have any thoughts on how to implement it without using commands that were removed from JavaScript back in 2011?
    that fallacious question impossible to answer.
    It's like asking "does the king of France have a beard?"
    the commands were deprecated, not removed; BIG difference!

    so the question is more accurately:
    "if I opt-out of Javascript's full available feature set, does this new feature work as shown?"

    The answer is no, of course not; it's among the features you chose to opt-out of. you can't eat the cake without eating the calories. Meanwhile this works forward and backwards for 5 years, not bad in this fast-moving enviroment; nothing's perfect or lasts forever.

    argument's "non arrayidness" is considered a bug. this code fixes that bug right now in the real world. To me, that's more valuable than pedantic conformance to a sub-section of some pdf somewhere... If they wouldn't have screwed the arguments up in the first place, we would need to use one bug to fix another.

    once ecma7 does come out, we'll have (hopefully) been able to use code like this for several years:

    Code:
    function sum(...args){
     return args.reduce( function(a,b){a+b} );
    }
    note the rest params and tail returns...

    meanwhile, "use strict" workarounds:
    1. use wrappers to turn arguments into an array
    2. remove the global "use strict" directive (as almost everyone recommends)
    3. load the script from an external script tag in a file that doesn't have "use strict".


    Those are all easy enough fixes.

    there are other shim-like workarounds, but they are WAY nastier than arr(arguments) and involve eval, dataURL-based scripts, throw, and a host of other nastiness.
    Last edited by rnd me; 02-24-2013 at 10:13 PM.
    my site (updated 13/9/26)
    BROWSER STATS [% share] (2014/9/03) IE7:0.1, IE8:4.6, IE11:9.1, IE9:3.1, IE10:3.0, FF:17.2, CH:46, SF:11.4, NON-MOUSE:38%

  • #8
    The fat guy next door VIPStephan's Avatar
    Join Date
    Jan 2006
    Location
    Halle (Saale), Germany
    Posts
    8,696
    Thanks
    6
    Thanked 1,011 Times in 984 Posts
    Although I’m not in any way proficient enough in ECMAScript to comment on the script itself, in philosophical and technical terms I tend to agree with Felgall (once more). I mean, if it all doesn’t matter what code we write and how we write it, why do people actually care to establish and advance standards?

    Oh and another philosophical point: People that lead a crowd are not necessarily more sensible than those late adopters that (inevitably) follow the crowd. We see that with HTML 5 where, instead of cleaning up the mess that piled up over the years (which they tried with HTML 4, XHTML 1 and the abandoned XHTML 2), they continued to use it and added yet more crap to it. Life could be so much easier and orderly if reason had prevailed over avidity. My point is: that crappy code exists and appears to work now doesn’t mean we shouldn’t strive for perfection anyway. HTML 5 isn’t a good example for that striving and so isn’t carelessness regarding best practices in programming.

    Just my two cents, for what it’s worth.

  • #9
    Master Coder felgall's Avatar
    Join Date
    Sep 2005
    Location
    Sydney, Australia
    Posts
    6,642
    Thanks
    0
    Thanked 649 Times in 639 Posts
    Quote Originally Posted by rnd me View Post
    heh; my point was actually what we should be using HTML5 now...
    Why? It is still some years off becoming a standard. The last time a lot of people started using something that a browser implemented before the standard was finished there were changes before it became a standard. The entire concept of quirks mode had to be invented because too many people jumped in early with CSS2 and used the IE5 implementation that wasn't the same as the final standard. I'd expect that a lot of those HTML 5 tags that are reintroductions of tags that were deleted for a reason will be removed again before HTML 5 becomes a standard - after all the reason that they were deleted in the first place is still there.

    Anyway from what I have been reading since you first opened this thread ECMAScript 6 is proposing to do away with arguments completely and replace it with a different method of accessing the unnamed arguments via an array.

    So instead of ECMAScript 5's:

    Code:
    function x() {
    args = [].slice.call(arguments);
    //code to use args as an array
    }
    ECMAScript 6 will apparently use the following new notation:

    Code:
    function x(...args) {
    //code to use args as an array
    }
    which is the lot less typing that you were referring to. So once ECMAScript 6 comes out arguments will be dead in the same way callee is dead in ECMAScript 5 and caller never existed as part of JavaScript in the first place (although some but not all browsers implement it but only if you don't specify that the code is ECMAScript 5).


    Note that I still think that the original concept is a good idea and we can't really wait for all browsers to implement the ECMAScript 6 replacement. That's why I am looking into a way that it might be done without relying on deprecated (ie. could be deleted any time and only still supported to give you time to rewrite your script to use a different way instead) and even more importantly without relying on a proprietary method that not all browsers support (caller).

    For example IE9 only supports caller if the page is running in quirks mode - as a non-standard call it isn't supported if the page is rendering in standards mode (ie if the page has a doctype). So it isn't just when you specify that you are using ECMAScript 5 that the code fails.

    With all the people using IE9 you really need a version of the code that will work for those people.
    Last edited by felgall; 02-25-2013 at 01:20 AM.
    Stephen
    Learn Modern JavaScript - http://javascriptexample.net/
    Helping others to solve their computer problem at http://www.felgall.com/

    Don't forget to start your JavaScript code with "use strict"; which makes it easier to find errors in your code.

  • #10
    Master Coder felgall's Avatar
    Join Date
    Sep 2005
    Location
    Sydney, Australia
    Posts
    6,642
    Thanks
    0
    Thanked 649 Times in 639 Posts
    Just found the following example on the Mozilla web site:

    Code:
    var unboundSlice = Array.prototype.slice;
    var slice = Function.prototype.call.bind(unboundSlice);
     
    function list() {
      return slice(arguments);
    }
     
    var list1 = list(1, 2, 3); // [1, 2, 3]
    So a more generic version of that could be:

    Code:
    var A = Function.prototype.call.bind(Array.prototype.slice); // only needed once
     
    function x() {
    args = A(arguments);
    //code to use args as an array
    }
    Last edited by felgall; 02-25-2013 at 04:37 AM.
    Stephen
    Learn Modern JavaScript - http://javascriptexample.net/
    Helping others to solve their computer problem at http://www.felgall.com/

    Don't forget to start your JavaScript code with "use strict"; which makes it easier to find errors in your code.

  • #11
    Senior Coder rnd me's Avatar
    Join Date
    Jun 2007
    Location
    Urbana
    Posts
    4,371
    Thanks
    11
    Thanked 591 Times in 572 Posts
    Quote Originally Posted by felgall View Post
    Just found the following example on the Mozilla web site:
    is there an echo in here? hehe

    that's the same routine as in the OP...
    i guess you've never had the pleasure of RSI.

    i also posted the rest param example several posts ago, and noted how we should switch to it when it's well supported.

    i've already incorporated a true-array args into my macro code-rewitter, init(), so it shouldn't be a problem for me to push out a conditional, just need a way to detect strict. i guess try catch can do the job until something better comes along.
    my site (updated 13/9/26)
    BROWSER STATS [% share] (2014/9/03) IE7:0.1, IE8:4.6, IE11:9.1, IE9:3.1, IE10:3.0, FF:17.2, CH:46, SF:11.4, NON-MOUSE:38%

  • #12
    Master Coder felgall's Avatar
    Join Date
    Sep 2005
    Location
    Sydney, Australia
    Posts
    6,642
    Thanks
    0
    Thanked 649 Times in 639 Posts
    Quote Originally Posted by rnd me View Post
    is there an echo in here? hehe

    that's the same routine as in the OP...
    Yes - except that I didn't recognise it until you pointed it out just now as you had abbreviated the portion of the code that you'd posted. Also when I replied to the first post I was more interested in the end result than I was in some of the alternatives you gave earlier. By the time I realised that your solution only works in ECMAScript 3 I had forgotten about the alternatives you'd posted.

    I guess that what my search ended up finding is an echo of one of the alternatives that you posted means that alternative is probably the best that can be done with ECMAScript 5.

    Now that IE9 has partly dropped support for the proprietary caller method it probably will not be long before the other browsers that support it do the same - particularly since none of them support it in ECMAScript 5.
    Stephen
    Learn Modern JavaScript - http://javascriptexample.net/
    Helping others to solve their computer problem at http://www.felgall.com/

    Don't forget to start your JavaScript code with "use strict"; which makes it easier to find errors in your code.

  • #13
    Master Coder felgall's Avatar
    Join Date
    Sep 2005
    Location
    Sydney, Australia
    Posts
    6,642
    Thanks
    0
    Thanked 649 Times in 639 Posts
    The following test to alert the arguments after sorting them avoids using the proprietary caller and dead callee commands but still unfortunately doesn't work in ECMAScript 5.

    Code:
    var A = function(f) {return [].slice.call(f.arguments);};
    
    var s = function() {
    alert(A(s).sort());
    };
    
    s(3,2,7);
    It looks like in the latest JavaScript you can't access the arguments from outside of the function itself (as the error says f.arguments is not accessible) so the closest you can get to that which will actually work is:

    Code:
    var A = function(a) {return [].slice.call(a);};
    
    var s = function() {
    alert(A(arguments).sort());
    };
    
    s(3,2,7);
    Last edited by felgall; 02-25-2013 at 08:44 AM.
    Stephen
    Learn Modern JavaScript - http://javascriptexample.net/
    Helping others to solve their computer problem at http://www.felgall.com/

    Don't forget to start your JavaScript code with "use strict"; which makes it easier to find errors in your code.

  • #14
    Senior Coder rnd me's Avatar
    Join Date
    Jun 2007
    Location
    Urbana
    Posts
    4,371
    Thanks
    11
    Thanked 591 Times in 572 Posts
    ecma6 bans the arguments.caller in strict, ecma5 left it alone.
    arguments.caller was never defined, and don't recommend anyone use it.
    It's arguments.callee.caller that works in all browsers i tested (unless you disable it with strict).

    One thing that i think is funny is that you can do this:
    Code:
    alert(Function('a',' "use strict"; return a*a;')(123))

    Thanks for looking into a work around. Looks like we're stuck with dynamic code generation if we want raw power and less typing.


    Sadly, Function is not avail under strict either, but <scirpt src=dataURLs> is, so we just have to rewrite all the function-type globals we find with the new code, encode that as a dataURL, inject the script, and resume on onload, ready, or wherever else it was waiting on us.

    That will let me not only fix arguments, it can add in a lot of missing features and fix common shortcomings and errors.

    basically, it's a play off of coffeescript, except that it uses valid JS syntax instead of something that must be delivered as a string. to scan the globals, i use something like this:

    Code:
    Object.keys(window).filter(function(a){
       if(window[a] && window[a].call && !String(window[a]).match(/\[native code\]/) && String(window[a]).match(/\bfor/)  ){ 
         return true;
        }
    })
    I see this as THE solution to a lot of things going forward.

    which gives me a list of all global user-land functions. I then grab those functions, make string replacements, and putting them in an output array. Ex: rewriting "ARGS" to "[].slice.call(arguments)". The output array is then joined, turning the functions into code, and that code is injected into the page using a dataURL-based script to avoid a direct call to eval.
    there would be no chance of "use strict" making it into the "file", so it should work work regardless of other code.


    The code in the OP was more of a discovery than an invention; i couldn't belive it would work without eval, and left me wondering how come i didn't see such delightful magic earlier: it's worked for a long time now...


    one last hurrah (sorry can't resist: you started it...)
    the opening intro of the MDN article call strict mode a subset (though not JUST one) and says it's an opt-in variant, not the future path forward:
    ECMAScript 5's strict mode is a way to opt in to a restricted variant of JavaScript. Strict mode isn't just a subset: it intentionally has different semantics from normal code.
    my site (updated 13/9/26)
    BROWSER STATS [% share] (2014/9/03) IE7:0.1, IE8:4.6, IE11:9.1, IE9:3.1, IE10:3.0, FF:17.2, CH:46, SF:11.4, NON-MOUSE:38%


  •  

    Tags for this Thread

    Posting Permissions

    • You may not post new threads
    • You may not post replies
    • You may not post attachments
    • You may not edit your posts
    •