Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Identifier like "_", "$", etc.

6 views
Skip to first unread message

Asen Bozhilov

unread,
Nov 9, 2009, 3:41:03 PM11/9/09
to
I read ajaxian.com. There i found one post which presented one new
JavaScript framework. The name of the framework is call "Underscore".
<URL: http://documentcloud.github.com/underscore/>

| Underscore is a utility-belt library for JavaScript that provides
| a lot of the functional programming support that you would
| expect in Prototype.js (or Ruby),
| but without extending any of the built-in JavaScript objects. It's
the tie to go along with jQuery's tux.

This is the first sentence in the page, that page must be
documentation of framework. I don't like style like this. When you
created framework, lived alone another framework. They have own
problems and own advantages. However, if anybody want to see source
code of "Underscore":
<URL: http://documentcloud.github.com/underscore/underscore.js>

The concern of the topic is identifiers name. What is the benefit from
identifier like:
_
$

I associated underscore with properties whos been "private". So i
don't make documentation for properties who identifier name start with
underscore.
$ symbol in normal live i associated with USA dollar. In Ecma3:

| 7.6 Identifiers
| 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.

So using $ for identifier name from programmers will be means
contradiction with ECMA3 documentation.

I want signed identifiers, who means what exactly contains or doing.
If i follow that fashion, soon i will be defined identifier like this
one:

var лев = "bg currency lev";

That is completely valid identifier, and its only two character much
more from $.

David Mark

unread,
Nov 9, 2009, 4:02:03 PM11/9/09
to
On Nov 9, 3:41 pm, Asen Bozhilov <asen.bozhi...@gmail.com> wrote:
> I read ajaxian.com. There i found one post which presented one new
> JavaScript framework. The name of the framework is call "Underscore".
> <URL:http://documentcloud.github.com/underscore/>
>
> | Underscore is a utility-belt library for JavaScript that provides
> | a lot of the functional programming support that you would
> | expect in Prototype.js  (or Ruby),
> | but without extending any of the built-in JavaScript objects. It's
> the tie to go along with jQuery's tux.

None of that makes sense. For one, functional programming support is
not what I would expect from Prototype. And jQuery is more of a clown
suit than a tux.

>
> This is the first sentence in the page, that page must be
> documentation of framework. I don't like style like this. When you
> created framework, lived alone another framework. They have own
> problems and own advantages.  However, if anybody want to see source
> code of "Underscore":
> <URL:http://documentcloud.github.com/underscore/underscore.js>

// Is a given array or object empty?
_.isEmpty = function(obj) {
return (_.isArray(obj) ? obj : _.values(obj)).length == 0;
};

Searching a script for "isArray" is a little like searching for
"mavigator.userAgent" (discard on discovery).

>
> The concern of the topic is identifiers name. What is the benefit from
> identifier like:
> _
> $

Zero, unless you've never heard of keyboard macros. Most of these
scripts end up minified anyway (and/or compressed by the server,
modems, etc.), so ridiculous variable names like this are of no
practical value (in fact, it makes for illegible scripts).

>
> I associated underscore with properties whos been "private". So i
> don't make documentation for properties who identifier name start with
> underscore.

Especially for a language without private members. ;)

> $ symbol in normal live i associated with USA dollar. In Ecma3:

As do most.

>
> | 7.6 Identifiers
> | 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.
>
> So using $ for identifier name from programmers will be means
> contradiction with ECMA3 documentation.

Yes, it is also seen as bad practice.

Peter Michaux

unread,
Nov 9, 2009, 4:07:40 PM11/9/09
to
On Nov 9, 2:41 pm, Asen Bozhilov <asen.bozhi...@gmail.com> wrote:
> I read ajaxian.com. There i found one post which presented one new
> JavaScript framework. The name of the framework is call "Underscore".
> <URL:http://documentcloud.github.com/underscore/>
>
> | Underscore is a utility-belt library for JavaScript that provides
> | a lot of the functional programming support that you would
> | expect in Prototype.js  (or Ruby),
> | but without extending any of the built-in JavaScript objects. It's
> the tie to go along with jQuery's tux.
>
> This is the first sentence in the page, that page must be
> documentation of framework. I don't like style like this. When you
> created framework, lived alone another framework. They have own
> problems and own advantages.  However, if anybody want to see source
> code of "Underscore":
> <URL:http://documentcloud.github.com/underscore/underscore.js>
>
> The concern of the topic is identifiers name. What is the benefit from
> identifier like:
> _
> $

I think the benefit is they are short. Too short and cryptic, I think.

> I associated underscore with properties whos been "private". So i
> don't make documentation for properties who identifier name start with
> underscore.
> $ symbol in normal live i associated with USA dollar. In Ecma3:
>
> | 7.6 Identifiers
> | 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.
>
> So using $ for identifier name from programmers will be means
> contradiction with ECMA3 documentation.

The use of $ in an indentifier doesn't contradict ECMAScript 3 because
$ was "intended for" not "reserved for". This issue has been discussed
in c.l.js many times. I believe this statement is gone from the
proposed ECMAScript 5 and if so I think it is good they removed it.

Peter

David Mark

unread,
Nov 9, 2009, 5:34:08 PM11/9/09
to
On Nov 9, 3:41 pm, Asen Bozhilov <asen.bozhi...@gmail.com> wrote:
> I read ajaxian.com. There i found one post which presented one new
> JavaScript framework. The name of the framework is call "Underscore".
> <URL:http://documentcloud.github.com/underscore/>
>
> | Underscore is a utility-belt library for JavaScript that provides
> | a lot of the functional programming support that you would
> | expect in Prototype.js  (or Ruby),
> | but without extending any of the built-in JavaScript objects. It's
> the tie to go along with jQuery's tux.
>
> This is the first sentence in the page, that page must be
> documentation of framework. I don't like style like this. When you
> created framework, lived alone another framework. They have own
> problems and own advantages.  However, if anybody want to see source
> code of "Underscore":
> <URL:http://documentcloud.github.com/underscore/underscore.js>
>

// Underscore.js
// (c) 2009 Jeremy Ashkenas, DocumentCloud Inc.
// Underscore is freely distributable under the terms of the MIT
license.
// Portions of Underscore are inspired by or borrowed from
Prototype.js,
// Oliver Steele's Functional, and John Resig's Micro-Templating.
// For all details and documentation:
// http://documentcloud.github.com/underscore/

Considering what follows, there seems to be at least one glaring
omission.


(function() {

/*------------------------- Baseline setup
---------------------------------*/

// Establish the root object, "window" in the browser, or "global"
on the server.
var root = this;

Oops, that is supposed to come first. :)


// Save the previous value of the "_" variable.
var previousUnderscore = root._;


That's jQuery, so quite an eclectic mix.


// If Underscore is called as a function, it returns a wrapped
object that
// can be used OO-style. This wrapper holds altered versions of all
the
// underscore functions. Wrapped objects may be chained.
var wrapper = function(obj) { this._wrapped = obj; };


That too.


// Create a safe reference to the Underscore object for reference
below.
var _ = root._ = function(obj) { return new wrapper(obj); };


A safe reference?


// Export the Underscore object for CommonJS.
if (typeof exports !== 'undefined') _ = exports;


Waste of time.


// Current version.
_.VERSION = '0.4.2';

/*------------------------ Collection Functions:
---------------------------*/

// The cornerstone, an each implementation.
// Handles objects implementing forEach, arrays, and raw objects.


Where have I seen this before?


_.each = function(obj, iterator, context) {
var index = 0;
try {
if (obj.forEach) {
obj.forEach(iterator, context);
} else if (obj.length) {
for (var i=0, l = obj.length; i<l; i++) iterator.call(context,
obj[i], i, obj);
} else {
for (var key in obj) if (Object.prototype.hasOwnProperty.call
(obj, key)) {
iterator.call(context, obj[key], key, obj);
}
}
} catch(e) {
if (e != '__break__') throw e;
}
return obj;
};


Well, not like _that_ anyway. :(


/* ----------------------- Function Functions:
-----------------------------*/

// Create a function bound to a given object (assigning 'this', and
arguments,
// optionally). Binding with arguments is also known as 'curry'.
_.bind = function(func, context) {
context = context || root;
var args = _.toArray(arguments).slice(2);
return function() {
var a = args.concat(_.toArray(arguments));
return func.apply(context, a);
};
};

// Bind all of an object's methods to that object. Useful for
ensuring that
// all callbacks defined on an object belong to it.
_.bindAll = function() {
var args = _.toArray(arguments);
var context = args.pop();
_.each(args, function(methodName) {
context[methodName] = _.bind(context[methodName], context);
});
};


Bind by method name with an optional context. Deja vu.


// Extend a given object with all of the properties in a source
object.
_.extend = function(destination, source) {
for (var property in source) destination[property] = source
[property];
return destination;
};

// Create a (shallow-cloned) duplicate of an object.
_.clone = function(obj) {
if (_.isArray(obj)) return obj.slice(0);
return _.extend({}, obj);
};


Prototypian (i.e. backwards approach to inheritance).


// Perform a deep comparison to check if two objects are equal.
_.isEqual = function(a, b) {
// Check object identity.
if (a === b) return true;

Waste of time.

// Different types?
var atype = typeof(a), btype = typeof(b);
if (atype != btype) return false;
// Basic equality test (watch out for coercions).
if (a == b) return true;
// One of them implements an isEqual()?
if (a.isEqual) return a.isEqual(b);
// If a is not an object by this point, we can't handle it.
if (atype !== 'object') return false;


Strict comparison is unneeded here.


// Nothing else worked, deep compare the contents.


Of course, typeof null == 'object'


var aKeys = _.keys(a), bKeys = _.keys(b);


So no wonder there is a try-catch in _each.

// Different object sizes?
if (aKeys.length != bKeys.length) return false;
// Recursive comparison of contents.
for (var key in a) if (!_.isEqual(a[key], b[key])) return false;

That's not going to work at all for null (or very well for Object
objects as the loop is unfiltered).

return true;
};

// Is a given array or object empty?
_.isEmpty = function(obj) {
return (_.isArray(obj) ? obj : _.values(obj)).length == 0;
};


This is a bad design (differentiating between Object and Array
objects). Perhaps the competent alternative was not "cool"
enough. :)


// Is a given value a DOM element?
_.isElement = function(obj) {
return !!(obj && obj.nodeType == 1);
};


Even worse (trying to differentiate between host and Object objects).
Cool though!


// Is a given value a real Array?
_.isArray = function(obj) {
return Object.prototype.toString.call(obj) == '[object Array]';
};


Always an indication of a bad script. And this "Miller
device" (quotes indicate the technique doesn't originate with that
guy) is not 100% reliable (as discussed here repeatedly).


// Is a given value a Function?
_.isFunction = function(obj) {
return Object.prototype.toString.call(obj) == '[object Function]';
};


Well, this one is just silly. Could use typeof for Function objects,
of course, but I imagine this is aimed at developers who wish to
design applications that must differentiate between host object
methods and native functions. Why such designs would ever be
considered is beyond me.


// Is a given variable undefined?
_.isUndefined = function(obj) {
return typeof obj == 'undefined';
};


Didn't need that.


/* -------------------------- Utility Functions:
-------------------------- */

// Run Underscore.js in noConflict mode, returning the '_' variable
to its
// previous owner. Returns a reference to the Underscore object.
_.noConflict = function() {
root._ = previousUnderscore;
return this;
};


Stay off the jQuery.


// Keep the identity function around for default iterators.
_.identity = function(value) {
return value;
};

// Break out of the middle of an iteration.
_.breakLoop = function() {
throw "__break__";
};


OMG.


// Generate a unique integer id (unique within the entire client
session).
// Useful for temporary DOM ids.
var idCounter = 0;
_.uniqueId = function(prefix) {
var id = idCounter++;
return prefix ? prefix + id : id;
};


Yeah, that rings a bell.


// Return a sorted list of the function names available in
Underscore.
_.functions = function() {
var functions = [];
for (var key in _) if (Object.prototype.hasOwnProperty.call(_,
key))


Except in agents that do not support hasOwnProperty.


functions.push(key);
return _.without(functions, 'VERSION', 'prototype',
'noConflict').sort();
};

// JavaScript templating a-la ERB, pilfered from John Resig's
// "Secrets of the JavaScript Ninja", page 83.


Yikes. That's the one with the Samurai right? Written long before
Resig had graduated from browser sniffing to object inferences. Not a
good reference for writing a JS anything, let alone a GP library.


_.template = function(str, data) {
var fn = new Function('obj',
'var p=[],print=function(){p.push.apply(p,arguments);};' +
'with(obj){p.push(\'' +
str
.replace(/[\r\t\n]/g, " ")
.split("<%").join("\t")
.replace(/((^|%>)[^\t]*)'/g, "$1\r")
.replace(/\t=(.*?)%>/g, "',$1,'")
.split("\t").join("');")
.split("%>").join("p.push('")
.split("\r").join("\\'")
+ "');}return p.join('');");
return data ? fn(data) : fn;
};

/*------------------------------- Aliases
----------------------------------*/

_.forEach = _.each;
_.foldl = _.inject = _.reduce;
_.foldr = _.reduceRight;
_.filter = _.select;
_.every = _.all;
_.some = _.any;
_.methods = _.functions;


Why?


/*------------------------ Setup the OOP Wrapper:
--------------------------*/

// Helper function to continue chaining intermediate results.
var result = function(obj, chain) {
return chain ? _(obj).chain() : obj;
};

// Add all of the Underscore functions to the wrapper object.
_.each(_.functions(), function(name) {
wrapper.prototype[name] = function() {
Array.prototype.unshift.call(arguments, this._wrapped);
return result(_[name].apply(_, arguments), this._chain);
};
});

// Add all mutator Array functions to the wrapper.
_.each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice',
'unshift'], function(name) {
wrapper.prototype[name] = function() {
Array.prototype[name].apply(this._wrapped, arguments);
return result(this._wrapped, this._chain);
};
});

// Add all accessor Array functions to the wrapper.
_.each(['concat', 'join', 'slice'], function(name) {
wrapper.prototype[name] = function() {
return result(Array.prototype[name].apply(this._wrapped,
arguments), this._chain);
};
});

// Start chaining a wrapped Underscore object.
wrapper.prototype.chain = function() {
this._chain = true;
return this;
};

// Extracts the result from a wrapped and chained object.
wrapper.prototype.value = function() {
return this._wrapped;
};

})();

Definitely saw this ending coming. ;) All in all, a mishmash of
ideas (most of the bad). I need a rubber stamp that reads "Avoid like
the Plague".

Michael Haufe ("TNO")

unread,
Nov 9, 2009, 5:37:12 PM11/9/09
to
On Nov 9, 2:41 pm, Asen Bozhilov <asen.bozhi...@gmail.com> wrote:
> The concern of the topic is identifiers name. What is the benefit from
> identifier like:
> _
> $

It all stemmed from the desire to keep 3rd party code out of the
global space. As a result, many major libraries have their own
"namespace" where they keep their code. In the case of jQuery, and its
fad with having the most terse syntax as possible, their "namespace"
became the "$" symbol. The assumption was that no other library or
code would have a global variable with that name, while at the same
time being as short as possible. Since jQuery became popular (due to
good and bad marketing), many wannabe libraries think a small global
"namespace" like that is a good idea, so monkey see monkey do. This is
my unqualified opinion though, so take it with a grain of salt.

David Mark

unread,
Nov 9, 2009, 5:46:15 PM11/9/09
to
On Nov 9, 5:37 pm, "Michael Haufe (\"TNO\")"

<t...@thenewobjective.com> wrote:
> On Nov 9, 2:41 pm, Asen Bozhilov <asen.bozhi...@gmail.com> wrote:
>
> > The concern of the topic is identifiers name. What is the benefit from
> > identifier like:
> > _
> > $
>
> It all stemmed from the desire to keep 3rd party code out of the
> global space. As a result, many  major libraries have their own
> "namespace" where they keep their code.

There's really no such thing as a "major" library. I know what you
mean though. Basically, "major" is synonymous with incompetent. How
many of these "majors" can even read an attribute straight? Odd trend
when you consider most hang their hats on CSS selector queries.

> In the case of jQuery, and its
> fad with having the most terse syntax as possible, their "namespace"
> became the "$" symbol. The assumption was that no other library or
> code would have a global variable with that name, while at the same
> time being as short as possible.

And what a monumentally stupid assumption as Prototype came out before
jQuery.

> Since jQuery became popular (due to
> good and bad marketing), many wannabe libraries think a small global
> "namespace" like that is a good idea, so monkey see monkey do.

I can't understand why so many of them wanna produce lousy, legless
scripts. It's as if incompetence and relevance are seen as linked. A
lot of the copied "majors" are on fumes at this point (and soon to be
rusting in the berm). Copying them is a sure path to nowhere.

Thomas 'PointedEars' Lahn

unread,
Nov 9, 2009, 6:02:58 PM11/9/09
to
Peter Michaux wrote:

This is the same in green.

> This issue has been discussed in c.l.js many times.

But the arguments did not get through to you anyway?

> I believe this statement is gone from the proposed ECMAScript 5 and if so
> I think it is good they removed it.

Well, I for one do not want to see code like the following spreading around:

<?php
$bar = 'baz';
$foo = 'bar';
echo <<<JS
\$foo.\$ = '{$$foo}';
JS;
?>

Do you?


PointedEars
--
realism: HTML 4.01 Strict
evangelism: XHTML 1.0 Strict
madness: XHTML 1.1 as application/xhtml+xml
-- Bjoern Hoehrmann

kangax

unread,
Nov 9, 2009, 6:27:25 PM11/9/09
to
David Mark wrote:
> On Nov 9, 3:41 pm, Asen Bozhilov <asen.bozhi...@gmail.com> wrote:
>> I read ajaxian.com. There i found one post which presented one new
>> JavaScript framework. The name of the framework is call "Underscore".
>> <URL:http://documentcloud.github.com/underscore/>
>>
>> | Underscore is a utility-belt library for JavaScript that provides
>> | a lot of the functional programming support that you would
>> | expect in Prototype.js (or Ruby),
>> | but without extending any of the built-in JavaScript objects. It's
>> the tie to go along with jQuery's tux.
>>
>> This is the first sentence in the page, that page must be
>> documentation of framework. I don't like style like this. When you
>> created framework, lived alone another framework. They have own
>> problems and own advantages. However, if anybody want to see source
>> code of "Underscore":
>> <URL:http://documentcloud.github.com/underscore/underscore.js>
>>

[...]

>
> // Export the Underscore object for CommonJS.
> if (typeof exports !== 'undefined') _ = exports;
>
>
> Waste of time.

Why?

[...]

>
>
> _.each = function(obj, iterator, context) {
> var index = 0;
> try {
> if (obj.forEach) {
> obj.forEach(iterator, context);
> } else if (obj.length) {
> for (var i=0, l = obj.length; i<l; i++) iterator.call(context,
> obj[i], i, obj);
> } else {
> for (var key in obj) if (Object.prototype.hasOwnProperty.call
> (obj, key)) {
> iterator.call(context, obj[key], key, obj);
> }
> }
> } catch(e) {
> if (e != '__break__') throw e;
> }
> return obj;
> };
>
>
> Well, not like _that_ anyway. :(

Pretty bad, indeed.

>
>
> /* ----------------------- Function Functions:
> -----------------------------*/
>
> // Create a function bound to a given object (assigning 'this', and
> arguments,
> // optionally). Binding with arguments is also known as 'curry'.
> _.bind = function(func, context) {
> context = context || root;
> var args = _.toArray(arguments).slice(2);
> return function() {
> var a = args.concat(_.toArray(arguments));
> return func.apply(context, a);
> };
> };
>
> // Bind all of an object's methods to that object. Useful for
> ensuring that
> // all callbacks defined on an object belong to it.
> _.bindAll = function() {
> var args = _.toArray(arguments);
> var context = args.pop();
> _.each(args, function(methodName) {
> context[methodName] = _.bind(context[methodName], context);
> });
> };
>
>
> Bind by method name with an optional context. Deja vu.

Clearly, not the most efficient implementation of bind.

>
>
> // Extend a given object with all of the properties in a source
> object.
> _.extend = function(destination, source) {
> for (var property in source) destination[property] = source
> [property];
> return destination;
> };

Where's DontEnum bug workaround?

>
> // Create a (shallow-cloned) duplicate of an object.
> _.clone = function(obj) {
> if (_.isArray(obj)) return obj.slice(0);
> return _.extend({}, obj);
> };
>
>
> Prototypian (i.e. backwards approach to inheritance).

What are you talking about? Prototype always used Lasse's clone/inherit
-like approach.

>
>
> // Perform a deep comparison to check if two objects are equal.
> _.isEqual = function(a, b) {
> // Check object identity.
> if (a === b) return true;
>
> Waste of time.
>
> // Different types?
> var atype = typeof(a), btype = typeof(b);
> if (atype != btype) return false;
> // Basic equality test (watch out for coercions).
> if (a == b) return true;
> // One of them implements an isEqual()?
> if (a.isEqual) return a.isEqual(b);
> // If a is not an object by this point, we can't handle it.
> if (atype !== 'object') return false;

Fails when comparing NaN's, from what I can see.

>
>
> Strict comparison is unneeded here.
>
>
> // Nothing else worked, deep compare the contents.
>
>
> Of course, typeof null == 'object'
>
>
> var aKeys = _.keys(a), bKeys = _.keys(b);
>
>
> So no wonder there is a try-catch in _each.
>
> // Different object sizes?
> if (aKeys.length != bKeys.length) return false;
> // Recursive comparison of contents.
> for (var key in a) if (!_.isEqual(a[key], b[key])) return false;
>
> That's not going to work at all for null (or very well for Object
> objects as the loop is unfiltered).
>
> return true;
> };
>
> // Is a given array or object empty?
> _.isEmpty = function(obj) {
> return (_.isArray(obj) ? obj : _.values(obj)).length == 0;
> };
>
>
> This is a bad design (differentiating between Object and Array
> objects). Perhaps the competent alternative was not "cool"
> enough. :)
>
>
> // Is a given value a DOM element?
> _.isElement = function(obj) {
> return !!(obj && obj.nodeType == 1);
> };
>
>
> Even worse (trying to differentiate between host and Object objects).
> Cool though!

Are you sure? I thought this is for filtering out element nodes (from
comment, text, etc.).

>
>
> // Is a given value a real Array?
> _.isArray = function(obj) {
> return Object.prototype.toString.call(obj) == '[object Array]';
> };
>
>
> Always an indication of a bad script. And this "Miller
> device" (quotes indicate the technique doesn't originate with that
> guy) is not 100% reliable (as discussed here repeatedly).

It's good enough 99% of the time. Everything else can be considered
exception (e.g. cross-window object wrappers in IE).

>
>
> // Is a given value a Function?
> _.isFunction = function(obj) {
> return Object.prototype.toString.call(obj) == '[object Function]';
> };
>
>
> Well, this one is just silly. Could use typeof for Function objects,

Nope. Did you forget what typeof reports for regex objects in webkit?

> of course, but I imagine this is aimed at developers who wish to
> design applications that must differentiate between host object
> methods and native functions. Why such designs would ever be
> considered is beyond me.
>
>
> // Is a given variable undefined?
> _.isUndefined = function(obj) {
> return typeof obj == 'undefined';
> };
>
>
> Didn't need that.

How so?

Don't forget, operators are not first class objects in Javascript ;)

[...]

>
>
> // Keep the identity function around for default iterators.
> _.identity = function(value) {
> return value;
> };
>
> // Break out of the middle of an iteration.
> _.breakLoop = function() {
> throw "__break__";
> };
>
>
> OMG.

Yes, that's usually unnecessary. Makes things needlessly slow.

[...]

>
> _.template = function(str, data) {
> var fn = new Function('obj',
> 'var p=[],print=function(){p.push.apply(p,arguments);};' +
> 'with(obj){p.push(\'' +
> str
> .replace(/[\r\t\n]/g, " ")
> .split("<%").join("\t")
> .replace(/((^|%>)[^\t]*)'/g, "$1\r")
> .replace(/\t=(.*?)%>/g, "',$1,'")
> .split("\t").join("');")
> .split("%>").join("p.push('")
> .split("\r").join("\\'")
> + "');}return p.join('');");
> return data ? fn(data) : fn;
> };
>
> /*------------------------------- Aliases
> ----------------------------------*/
>
> _.forEach = _.each;
> _.foldl = _.inject = _.reduce;
> _.foldr = _.reduceRight;
> _.filter = _.select;
> _.every = _.all;
> _.some = _.any;
> _.methods = _.functions;
>
>
> Why?

Those on the left look like JS1.5 extensions / ES5 additions.

It's a clone of Prototype, stuffed into one object, instead of
augmenting built-ins.

--
kangax

David Mark

unread,
Nov 9, 2009, 7:51:50 PM11/9/09
to
On Nov 9, 6:27 pm, kangax <kan...@gmail.com> wrote:
> David Mark wrote:
> > On Nov 9, 3:41 pm, Asen Bozhilov <asen.bozhi...@gmail.com> wrote:
> >> I read ajaxian.com. There i found one post which presented one new
> >> JavaScript framework. The name of the framework is call "Underscore".
> >> <URL:http://documentcloud.github.com/underscore/>
>
> >> | Underscore is a utility-belt library for JavaScript that provides
> >> | a lot of the functional programming support that you would
> >> | expect in Prototype.js  (or Ruby),
> >> | but without extending any of the built-in JavaScript objects. It's
> >> the tie to go along with jQuery's tux.
>
> >> This is the first sentence in the page, that page must be
> >> documentation of framework. I don't like style like this. When you
> >> created framework, lived alone another framework. They have own
> >> problems and own advantages.  However, if anybody want to see source
> >> code of "Underscore":
> >> <URL:http://documentcloud.github.com/underscore/underscore.js>
>
> [...]
>
>
>
> >   // Export the Underscore object for CommonJS.
> >   if (typeof exports !== 'undefined') _ = exports;
>
> > Waste of time.
>
> Why?

Why export something that nobody wants or needs?

As to this loop, perhaps I am thinking of another library (or more
than one likely). But ISTM "extend" was part of Prototype's
implementation of classical inheritance for JS, which - next to
extending the Object prototype - was the biggest complaint about the
design of that library. Of course the implementation was always so
bad (e.g. browser sniffing) that it didn't merit much discussion.

No, I'm not sure. The name and comment seem to indicate a GP
function. But if so, it seems completely unneeded (all it does is
check if nodeType == 1). Certainly no good for GP usage.

>
>
>
> >   // Is a given value a real Array?
> >   _.isArray = function(obj) {
> >     return Object.prototype.toString.call(obj) == '[object Array]';
> >   };
>
> > Always an indication of a bad script.  And this "Miller
> > device" (quotes indicate the technique doesn't originate with that
> > guy) is not 100% reliable (as discussed here repeatedly).
>
> It's good enough 99% of the time. Everything else can be considered
> exception (e.g. cross-window object wrappers in IE).

That's as maybe. It's never needed.

>
>
>
> >   // Is a given value a Function?
> >   _.isFunction = function(obj) {
> >     return Object.prototype.toString.call(obj) == '[object Function]';
> >   };
>
> > Well, this one is just silly.  Could use typeof for Function objects,
>
> Nope. Did you forget what typeof reports for regex objects in webkit?

Of course not. Second sentence in the documentation for such a
function (after host object warning) should be "Do not use with RegExp
objects". It stands to reason that a design that sets out to discern
between Function and RegExp objects is a design in need of a rewrite.

And none of these "overloading" functions are conducive to good design
anyway. If you consider a case that is do-able (e.g. string vs.
function), it boils down to the typeof operator. So why wrap that in
a function?

>
> > of course, but I imagine this is aimed at developers who wish to
> > design applications that must differentiate between host object
> > methods and native functions.  Why such designs would ever be
> > considered is beyond me.
>
> >   // Is a given variable undefined?
> >   _.isUndefined = function(obj) {
> >     return typeof obj == 'undefined';
> >   };
>
> > Didn't need that.
>
> How so?

Same reason you don't need an isFunction. Just use the typeof
operator and document accordingly.

>
> Don't forget, operators are not first class objects in Javascript ;)
>
> [...]
>
>
>
> >   // Keep the identity function around for default iterators.
> >   _.identity = function(value) {
> >     return value;
> >   };
>
> >   // Break out of the middle of an iteration.
> >   _.breakLoop = function() {
> >     throw "__break__";
> >   };
>
> > OMG.
>
> Yes, that's usually unnecessary. Makes things needlessly slow.

Besides that, what sort of design throws in the middle of a loop? And
who throws strings?

Nevertheless. It's their "namespace", so why the aliases?

I see MooTools as more of a clone of Prototype. This is just an
abbreviated mishmash. BTW, are you still working on that thing?

kangax

unread,
Nov 9, 2009, 11:38:37 PM11/9/09
to
David Mark wrote:
> On Nov 9, 6:27 pm, kangax <kan...@gmail.com> wrote:
>> David Mark wrote:
>>> On Nov 9, 3:41 pm, Asen Bozhilov <asen.bozhi...@gmail.com> wrote:
>>>> I read ajaxian.com. There i found one post which presented one new
>>>> JavaScript framework. The name of the framework is call "Underscore".
>>>> <URL:http://documentcloud.github.com/underscore/>
>>>> | Underscore is a utility-belt library for JavaScript that provides
>>>> | a lot of the functional programming support that you would
>>>> | expect in Prototype.js (or Ruby),
>>>> | but without extending any of the built-in JavaScript objects. It's
>>>> the tie to go along with jQuery's tux.
>>>> This is the first sentence in the page, that page must be
>>>> documentation of framework. I don't like style like this. When you
>>>> created framework, lived alone another framework. They have own
>>>> problems and own advantages. However, if anybody want to see source
>>>> code of "Underscore":
>>>> <URL:http://documentcloud.github.com/underscore/underscore.js>
>> [...]
[...]

>>> // Create a (shallow-cloned) duplicate of an object.
>>> _.clone = function(obj) {
>>> if (_.isArray(obj)) return obj.slice(0);
>>> return _.extend({}, obj);
>>> };
>>> Prototypian (i.e. backwards approach to inheritance).
>> What are you talking about? Prototype always used Lasse's clone/inherit
>> -like approach.
>
> As to this loop, perhaps I am thinking of another library (or more
> than one likely). But ISTM "extend" was part of Prototype's
> implementation of classical inheritance for JS, which - next to
> extending the Object prototype - was the biggest complaint about the
> design of that library. Of course the implementation was always so
> bad (e.g. browser sniffing) that it didn't merit much discussion.

`Object.extend` (i.e. simple copying of properties from one object to
another) has been in Prototype since its inception and was mainly a
plain general purpose helper.

The only way it was used in inheritance abstraction is to copy
properties onto constructor's prototype (so you would pass an object
into a helper rather than assign methods to constructor's prototype
manually).

Until recently, there was this idiotic sniff for `Browser.IE` when
working around DontEnum bug in `Object.extend`, but that's because none
of us seemed to know what it was (workaround was only taking care of
"toString" and "valueOf", and in a rather inefficient manner).

Actual inheritance, though, has always been done via Lasse clone/inherit
-like approach.

[...]

>>> // Is a given value a DOM element?
>>> _.isElement = function(obj) {
>>> return !!(obj && obj.nodeType == 1);
>>> };
>>> Even worse (trying to differentiate between host and Object objects).
>>> Cool though!
>> Are you sure? I thought this is for filtering out element nodes (from
>> comment, text, etc.).
>
> No, I'm not sure. The name and comment seem to indicate a GP
> function. But if so, it seems completely unneeded (all it does is
> check if nodeType == 1). Certainly no good for GP usage.

Yeah, that's pretty simplistic.

>
>>
>>
>>> // Is a given value a real Array?
>>> _.isArray = function(obj) {
>>> return Object.prototype.toString.call(obj) == '[object Array]';
>>> };
>>> Always an indication of a bad script. And this "Miller
>>> device" (quotes indicate the technique doesn't originate with that
>>> guy) is not 100% reliable (as discussed here repeatedly).
>> It's good enough 99% of the time. Everything else can be considered
>> exception (e.g. cross-window object wrappers in IE).
>
> That's as maybe. It's never needed.

I'm not a big fan of duck typing, but sure, that's another way :)

>
>>
>>
>>> // Is a given value a Function?
>>> _.isFunction = function(obj) {
>>> return Object.prototype.toString.call(obj) == '[object Function]';
>>> };
>>> Well, this one is just silly. Could use typeof for Function objects,
>> Nope. Did you forget what typeof reports for regex objects in webkit?
>
> Of course not. Second sentence in the documentation for such a
> function (after host object warning) should be "Do not use with RegExp
> objects". It stands to reason that a design that sets out to discern
> between Function and RegExp objects is a design in need of a rewrite.

But it's not even about discerning. What if regex ends up as an argument
of your function and that function invokes `call` on it after testing it
with `typeof`? regex don't have call (unless you give it to them) so it
will fail.

Too many limitations and exceptions is also annoying. What "too many"
means is of course subjective, and what's annoying to me might be fine
to you.

I don't see much harm in employing [[Class]] based test, though.

>
> And none of these "overloading" functions are conducive to good design
> anyway. If you consider a case that is do-able (e.g. string vs.
> function), it boils down to the typeof operator. So why wrap that in
> a function?

To abstract and provide a common interface. What else could be the reason.

>
>>> of course, but I imagine this is aimed at developers who wish to
>>> design applications that must differentiate between host object
>>> methods and native functions. Why such designs would ever be
>>> considered is beyond me.
>>> // Is a given variable undefined?
>>> _.isUndefined = function(obj) {
>>> return typeof obj == 'undefined';
>>> };
>>> Didn't need that.
>> How so?
>
> Same reason you don't need an isFunction. Just use the typeof
> operator and document accordingly.
>
>> Don't forget, operators are not first class objects in Javascript ;)
>>
>> [...]
>>
>>
>>
>>> // Keep the identity function around for default iterators.
>>> _.identity = function(value) {
>>> return value;
>>> };
>>> // Break out of the middle of an iteration.
>>> _.breakLoop = function() {
>>> throw "__break__";
>>> };
>>> OMG.
>> Yes, that's usually unnecessary. Makes things needlessly slow.
>
> Besides that, what sort of design throws in the middle of a loop? And
> who throws strings?

I suppose they throw to stop iteration (as Prototype does). Whether they
throw string or something else doesn't seem to make much difference.

Prototype realized that being able to stop iteration is not worth
performance hit of wrapping it with try-catch.

Maybe one day these guys will come to the same conclusion :)

[...]

Rarely.

Last couple of months I've been working on ECMAScript compliance test
suite that can be run a browser. It's actually just a wrapper around
Google's Sputniktests (thanks to Google for doing all the heavy work),
adopted for running in a web page.

Hopefully, this will eliminate most of the chaos in current
implementations and prevent regresssions in future work.

Check it out �
http://thinkweb2.com/projects/prototype/sputniktests-web-runner/

How is your dojo work going?

--
kangax

David Mark

unread,
Nov 10, 2009, 12:26:15 AM11/10/09
to

More of a hindrance it would seem. :)

>
> The only way it was used in inheritance abstraction is to copy
> properties onto constructor's prototype (so you would pass an object
> into a helper rather than assign methods to constructor's prototype
> manually).

Okay. So it is used to mix-in properties.

>
> Until recently, there was this idiotic sniff for `Browser.IE` when
> working around DontEnum bug in `Object.extend`, but that's because none
> of us seemed to know what it was (workaround was only taking care of
> "toString" and "valueOf", and in a rather inefficient manner).

Hopefully you replaced that with a feature test (and added the other
affected properties). But think of all of the Prototype-based sites
out there. They will have to upgrade the whole thing with all of the
other changes made to that project included and then start QA testing
from ground zero.

>
> Actual inheritance, though, has always been done via Lasse clone/inherit
> -like approach.

Okay. It's something about the construction of objects that was out
of line in that library.

>
> [...]
>
> >>>   // Is a given value a DOM element?
> >>>   _.isElement = function(obj) {
> >>>     return !!(obj && obj.nodeType == 1);
> >>>   };
> >>> Even worse (trying to differentiate between host and Object objects).
> >>> Cool though!
> >> Are you sure? I thought this is for filtering out element nodes (from
> >> comment, text, etc.).
>
> > No, I'm not sure.  The name and comment seem to indicate a GP
> > function.  But if so, it seems completely unneeded (all it does is
> > check if nodeType == 1).  Certainly no good for GP usage.
>
> Yeah, that's pretty simplistic.
>
>
>
> >>>   // Is a given value a real Array?
> >>>   _.isArray = function(obj) {
> >>>     return Object.prototype.toString.call(obj) == '[object Array]';
> >>>   };
> >>> Always an indication of a bad script.  And this "Miller
> >>> device" (quotes indicate the technique doesn't originate with that
> >>> guy) is not 100% reliable (as discussed here repeatedly).
> >> It's good enough 99% of the time. Everything else can be considered
> >> exception (e.g. cross-window object wrappers in IE).
>
> > That's as maybe.  It's never needed.
>
> I'm not a big fan of duck typing, but sure, that's another way :)

My point is that you can design your app so that it doesn't need to
tell an Array object from an Object object. Duck typing would be a
fallback for the "Miller Device" that could make an isArray (or
isWhatever) a bit closer to 100% reliable, but why bother?

>
>
>
> >>>   // Is a given value a Function?
> >>>   _.isFunction = function(obj) {
> >>>     return Object.prototype.toString.call(obj) == '[object Function]';
> >>>   };
> >>> Well, this one is just silly.  Could use typeof for Function objects,
> >> Nope. Did you forget what typeof reports for regex objects in webkit?
>
> > Of course not.  Second sentence in the documentation for such a
> > function (after host object warning) should be "Do not use with RegExp
> > objects".  It stands to reason that a design that sets out to discern
> > between Function and RegExp objects is a design in need of a rewrite.
>
> But it's not even about discerning. What if regex ends up as an argument
> of your function and that function invokes `call` on it after testing it
> with `typeof`? regex don't have call (unless you give it to them) so it
> will fail.

As it should. If the documentation stipulates No RegExp objects are
to be passed to this function, then the behavior with a RegExp
argument is undefined. It should be expected to fail when passed a
RegExp.

And, though irrelevant, I disagree that the RegExp in question is not
callable. Unless you mean calling its - call - method?

>
> Too many limitations and exceptions is also annoying. What "too many"
> means is of course subjective, and what's annoying to me might be fine
> to you.

An API should not enable bad design decisions. If you look at the
fact that most of the "majors" struggled with awful versions of these
is* "overloading" helpers. Wouldn't it have saved a lot of time to
determine they are a bad idea from the start?

>
> I don't see much harm in employing [[Class]] based test, though.

At the very least, the limitations should be documented. Advice to
avoid the function would make sense too, but I know that wouldn't be
cool.

>
>
>
> > And none of these "overloading" functions are conducive to good design
> > anyway.  If you consider a case that is do-able (e.g. string vs.
> > function), it boils down to the typeof operator.  So why wrap that in
> > a function?
>
> To abstract and provide a common interface. What else could be the reason.

I wasn't looking for an answer, just remarking that such an operation
is better left inline.

Seems like quite a difference to me.

>
> Prototype realized that being able to stop iteration is not worth
> performance hit of wrapping it with try-catch.

That's good.

>
> Maybe one day these guys will come to the same conclusion :)

The question is whether anyone will care. Waiting on "those guys" to
learn browser scripting has been the mantra for years. Look what a
mess that has made.

That's just a step away from never. :)

>
> Last couple of months I've been working on ECMAScript compliance test
> suite that can be run a browser. It's actually just a wrapper around
> Google's Sputniktests (thanks to Google for doing all the heavy work),
> adopted for running in a web page.
>
> Hopefully, this will eliminate most of the chaos in current
> implementations and prevent regresssions in future work.

One can only hope.

>
> Check it out —http://thinkweb2.com/projects/prototype/sputniktests-web-runner/

I will when I get a chance.

>
> How is your dojo work going?
>

Great, but now I'm too busy working on Dojo applications to work on
the project. I'll get back to it eventually. For now, I work around
the problems as that is where the money is. ;)

Richard Cornford

unread,
Nov 10, 2009, 6:31:14 AM11/10/09
to
On Nov 9, 9:07 pm, Peter Michaux wrote:
> On Nov 9, 2:41 pm, Asen Bozhilov wrote:
>
<snip>

>> The concern of the topic is identifiers name. What is the
>> benefit from identifier like:
>> _
>> $
>
> I think the benefit is they are short. Too short and cryptic,
> I think.

Yes, short and cryptic (or at least under-descriptive) names don't
contribute much to script authoring efforts as the little time they
may save in typing in code is almost certainly negated by orders of
magnitude of more time squandered during debugging/maintenance.

And then there is the hugely increased chance of naming collisions
which leaves the authors of, for example, JQurey code wrapping
everything they write in structures like:-

(function ($){
// actual code using $( ... )
})(JQurey);

- in order that "other code" that defines its own - $ - functions/
objects is not be impacted by Query's use of that identifier. If you
wanted something to flag a bad idea, finding yourself jumping through
hoops as a consequence (and in order to carry on doing it) is probably
as good an indicator as any. Still, some mistakes are difficult to
back out off, even when recognised.


>> I associated underscore with properties whos been "private".
>> So i don't make documentation for properties who identifier
>> name start with underscore.
>> $ symbol in normal live i associated with USA dollar. In Ecma3:
>
>> | 7.6 Identifiers
>> | 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.
>
>> So using $ for identifier name from programmers will be means
>> contradiction with ECMA3 documentation.
>
> The use of $ in an indentifier doesn't contradict ECMAScript 3
> because $ was "intended for" not "reserved for". This issue has
> been discussed in c.l.js many times. I believe this statement
> is gone from the proposed ECMAScript 5 and if so I think it is
> good they removed it.

The pragmatic recognition that the horse has long since bolted does
not imply approval of the actions of whoever let it out, or their
consequences.

Richard.

Tim Down

unread,
Nov 10, 2009, 9:40:16 AM11/10/09
to
On Nov 9, 10:34 pm, David Mark <dmark.cins...@gmail.com> wrote:
>     if (atype !== 'object') return false;
>
> Strict comparison is unneeded here.

I'm sure you've answered this before, but what is your beef with using
strict comparison operators when they're not needed? the only argument
I can see against it is the use of one extra character.


> And none of these "overloading" functions are conducive to good design
> anyway. If you consider a case that is do-able (e.g. string vs.
> function), it boils down to the typeof operator. So why wrap that in
> a function?

The benefit of using isWhatever functions for the doable cases is that
you remove the possibility of introducing bugs by mistyping the
comparison string ("function", "string", etc.) that exists if using
inline typeof comparisons.

Tim

Thomas 'PointedEars' Lahn

unread,
Nov 10, 2009, 1:12:14 PM11/10/09
to
Tim Down wrote:

> On Nov 9, 10:34 pm, David Mark <dmark.cins...@gmail.com> wrote:
>> if (atype !== 'object') return false;
>>
>> Strict comparison is unneeded here.
>
> I'm sure you've answered this before, but what is your beef with using
> strict comparison operators when they're not needed? the only argument
> I can see against it is the use of one extra character.

The latest test results for the local ECMAScript Support Matrix (checked in
yesterday) support that assessment. Transposed:

Feature: !==
Title: Strict Equals operator
JavaScript: 1.3
JScript: 5.1.5010
ECMAScript: 3
JSCore: 525.19
Opera: 5.02
KJS: 3.5.9

Corrections for earlier versions of the implementations are welcome.

>> And none of these "overloading" functions are conducive to good design
>> anyway. If you consider a case that is do-able (e.g. string vs.
>> function), it boils down to the typeof operator. So why wrap that in
>> a function?
>
> The benefit of using isWhatever functions for the doable cases is that
> you remove the possibility of introducing bugs by mistyping the
> comparison string ("function", "string", etc.) that exists if using
> inline typeof comparisons.

In a runtime environment with host-defined properties you cannot pass a
value if you do not know whether the identifier you are using a) resolves to
a property and b) if so, if that property stores a value that is suitable
for being passed. (That is why isMethod() primarily uses property names
now.)


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

Thomas 'PointedEars' Lahn

unread,
Nov 10, 2009, 1:18:06 PM11/10/09
to
Thomas 'PointedEars' Lahn wrote:

> Feature: !==
> Title: Strict Equals operator

Typo: Strict _Not_ Equals operator.

David Mark

unread,
Nov 10, 2009, 3:34:02 PM11/10/09
to
On Nov 10, 9:40 am, Tim Down <timd...@gmail.com> wrote:
> On Nov 9, 10:34 pm, David Mark <dmark.cins...@gmail.com> wrote:
>
> >     if (atype !== 'object') return false;
>
> > Strict comparison is unneeded here.
>
> I'm sure you've answered this before, but what is your beef with using
> strict comparison operators when they're not needed? the only argument
> I can see against it is the use of one extra character.

Because it makes the code harder to read. If I see a loose
comparison, I know the two operators are expected to be the same
type. A strict comparison warrants further investigation to determine
if it is needed (e.g. operand types can vary) or not.

>
> > And none of these "overloading" functions are conducive to good design
> > anyway.  If you consider a case that is do-able (e.g. string vs.
> > function), it boils down to the typeof operator.  So why wrap that in
> > a function?
>
> The benefit of using isWhatever functions for the doable cases is that
> you remove the possibility of introducing bugs by mistyping the
> comparison string ("function", "string", etc.) that exists if using
> inline typeof comparisons.

You don't have to compare the typeof result to string literals. In
fact, in a large project, I'd advised against that for just this
reason.

Garrett Smith

unread,
Nov 10, 2009, 3:42:34 PM11/10/09
to
kangax wrote:
> David Mark wrote:
>> On Nov 9, 6:27 pm, kangax <kan...@gmail.com> wrote:
>>> David Mark wrote:
>>>> On Nov 9, 3:41 pm, Asen Bozhilov <asen.bozhi...@gmail.com> wrote:
>>>>> I read ajaxian.com. There i found one post which presented one new
[...]

Ajaxian is a pop blog. Do not expect that to be a reliable source of
information on how to program.

>>>> Well, this one is just silly. Could use typeof for Function objects,
>>> Nope. Did you forget what typeof reports for regex objects in webkit?
>>
>> Of course not. Second sentence in the documentation for such a
>> function (after host object warning) should be "Do not use with RegExp
>> objects". It stands to reason that a design that sets out to discern
>> between Function and RegExp objects is a design in need of a rewrite.
>
> But it's not even about discerning. What if regex ends up as an argument
> of your function and that function invokes `call` on it after testing it
> with `typeof`? regex don't have call (unless you give it to them) so it
> will fail.
>

javascript: alert( Function.prototype.call.call(/a/, "a") );
Webkit:
elerts "a"

Tracemonkey:
TypeError: Function.prototype.call called on incompatible /a/

That's odd. Seems in Tracemonkey, a RegExp is callable without
implementing [[Call]], or ? A bug in there syntax extension, due
to internal typechecking for RegExp, as:
typeof /a/

Tracemonkey:
"object"

javascript: alert( /a/("a") );
elerts "a"

The documentation argument...

It is s silly presupposition that each function needs documentation.

Comments often do lie and this happens inadvertently when the program
changes.

Good comments help to explain code that is difficult, unusual, or
unintuitive. Bad comments lie, or don't lie but clutter the source code.

Many won't read the documentation of others (including pertinent
specifications, as witnessed recently on this NG). Developers often skip
right to the "what does it do" (functions, examples, or tests).

> Too many limitations and exceptions is also annoying. What "too many"
> means is of course subjective, and what's annoying to me might be fine
> to you.
>
> I don't see much harm in employing [[Class]] based test, though.
>

Where is typechecking necessary or useful?

Typechecking justifications are usually based on attempts to make
javascript appear more like some other language. For example, to
enabling fake overloading.

A generalized typecheck would be unreliable in the general sense
(fickle, dodgy host objects).

Typechecking is not usually needed and doesn't work for host objects.
It can be done inline, where needed.

Typechecking adds overhead to the code and increases call stack length.

[...]
--
Garrett
comp.lang.javascript FAQ: http://jibbering.com/faq/

Garrett Smith

unread,
Nov 10, 2009, 3:56:28 PM11/10/09
to
Tim Down wrote:
> On Nov 9, 10:34 pm, David Mark <dmark.cins...@gmail.com> wrote:
>> if (atype !== 'object') return false;
>>
>> Strict comparison is unneeded here.
>
> I'm sure you've answered this before, but what is your beef with using
> strict comparison operators when they're not needed? the only argument
> I can see against it is the use of one extra character.
>
Agreed, focusing on that "issue" seems to miss the point.

The strict equality operator (===), will have slightly faster
performance in at least one implementation (JScript). The benefit is
negligible. The cost of the one extra character is also negligible.

>
>> And none of these "overloading" functions are conducive to good design
>> anyway. If you consider a case that is do-able (e.g. string vs.
>> function), it boils down to the typeof operator. So why wrap that in
>> a function?
>
> The benefit of using isWhatever functions for the doable cases is that
> you remove the possibility of introducing bugs by mistyping the
> comparison string ("function", "string", etc.) that exists if using
> inline typeof comparisons.
>

Couldn't |isWhatever| be mistyped?

If autocomplete is desirable, constants can be used.

var FUNCTION = "function";

if(FUNCTION === typeof obj.eventHook) {
obj.eventHook( {/*...*/} );
}

Those constants would be munged. Performance would probably slower than
string literal, though only by a negligible amount (when in same scope).

Compared to the performance of calling isWhatever, the performance would
be better (unless the interpreter provides some sort of inline
optimization).

David Mark

unread,
Nov 10, 2009, 3:56:32 PM11/10/09
to

That's the stupidest thing I ever heard.

>
> Comments often do lie and this happens inadvertently when the program
> changes.

So, you are projecting your own habits on the rest of the programming
community?

>
> Good comments help to explain code that is difficult, unusual, or
> unintuitive. Bad comments lie, or don't lie but clutter the source code.

You sound like VK again.

>
> Many won't read the documentation of others (including pertinent
> specifications, as witnessed recently on this NG).

Specs aren't docs if they don't reflect reality. Seems you are still
stewing about that thread. Get over it.

> Developers often skip
> right to the "what does it do" (functions, examples, or tests).

So? If they don't read the documentation before using a function,
then that's there problem. And that's true for any API.

>
> > Too many limitations and exceptions is also annoying. What "too many"
> > means is of course subjective, and what's annoying to me might be fine
> > to you.
>
> > I don't see much harm in employing [[Class]] based test, though.
>
> Where is typechecking necessary or useful?

Thanks, professor. That has been the point all along.

>
> Typechecking justifications are usually based on attempts to make
> javascript appear more like some other language. For example, to
> enabling fake overloading.

Why regurgitate all of this at this point?

>
> A generalized typecheck would be unreliable in the general sense
> (fickle, dodgy host objects).

Thank you.

>
> Typechecking is not usually needed and doesn't work for host objects.

And again.

> It can be done inline, where needed.

So, you agree to agree on all of the points made? What was your
point?


>
> Typechecking adds overhead to the code and increases call stack length.

Certainly not the latter. I'm sure you mean that calling functions
increases the call stack length.

Garrett Smith

unread,
Nov 10, 2009, 4:05:29 PM11/10/09
to
Garrett Smith wrote:
> kangax wrote:
>> David Mark wrote:
>>> On Nov 9, 6:27 pm, kangax <kan...@gmail.com> wrote:
>>>> David Mark wrote:
>>>>> On Nov 9, 3:41 pm, Asen Bozhilov <asen.bozhi...@gmail.com> wrote:

[...]


> Typechecking adds overhead to the code and increases call stack length.
>

Correction: Calls to typechecking functions add overhead...

Thomas 'PointedEars' Lahn

unread,
Nov 10, 2009, 8:43:38 PM11/10/09
to
Garrett Smith wrote:

> It is s silly presupposition that each function needs documentation.
>
> Comments often do lie and this happens inadvertently when the program
> changes.

Don't drink and derive!


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

kangax

unread,
Nov 10, 2009, 9:39:28 PM11/10/09
to

Yes, from what I remember, Mozilla makes regex objects callable without
actually giving them [[Call]].

In WebKit, on the other hand, regex do have [[Call]] and so typeof
returns "function", as per specs (native object + has [[Call]] ==
"function").

You can find few related discussions on es-discuss ML's.

I mentioned it recently among some of the issues revealed through
Sputniktests �
http://thinkweb2.com/projects/prototype/sputniktests-web-runner/#typeof-new-regexp-function

>
> Tracemonkey:
> "object"
>
> javascript: alert( /a/("a") );
> elerts "a"
>
> The documentation argument...
>
> It is s silly presupposition that each function needs documentation.
>
> Comments often do lie and this happens inadvertently when the program
> changes.
>
> Good comments help to explain code that is difficult, unusual, or
> unintuitive. Bad comments lie, or don't lie but clutter the source code.
>
> Many won't read the documentation of others (including pertinent
> specifications, as witnessed recently on this NG). Developers often skip
> right to the "what does it do" (functions, examples, or tests).

It's no surprise that ES3 specs are hard to follow and full of
ambiguities. A year ago, the only way I could understand certain things
in specs is with the help of wonderful explanations by Cornford and
Lasse in the archives (on related subjects).

Your last question on es-discuss proves how hard it could be to discern
specs correctly.

ES5, fortunately, takes care of some of these uncertainties.

>
>> Too many limitations and exceptions is also annoying. What "too many"
>> means is of course subjective, and what's annoying to me might be fine
>> to you.
>>
>> I don't see much harm in employing [[Class]] based test, though.
>>
>
> Where is typechecking necessary or useful?
>
> Typechecking justifications are usually based on attempts to make
> javascript appear more like some other language. For example, to
> enabling fake overloading.

I have no experience with other languages, but I still find type
checking useful. I find it easier to read and cleaner overall to have
`isArray(something)` rather than `typeof something.length == "number"`.
When I read the latter one in the code, my mind still automatically
translates it to the former one � "Oh, ok... here we're checking if
something is array...".

It's not a big deal, though. I don't care much which one to use. I just
prefer abstracted type checking, as I find it to convey overall meaning
better. That's all, really.

[...]

>
> Typechecking adds overhead to the code and increases call stack length.

Well that much is obvious :) So is every other kind of abstraction,
doesn't it?

>
> [...]

--
kangax

kangax

unread,
Nov 10, 2009, 9:45:00 PM11/10/09
to
Thomas 'PointedEars' Lahn wrote:
> Tim Down wrote:
>
>> On Nov 9, 10:34 pm, David Mark <dmark.cins...@gmail.com> wrote:
>>> if (atype !== 'object') return false;
>>>
>>> Strict comparison is unneeded here.
>> I'm sure you've answered this before, but what is your beef with using
>> strict comparison operators when they're not needed? the only argument
>> I can see against it is the use of one extra character.
>
> The latest test results for the local ECMAScript Support Matrix (checked in
> yesterday) support that assessment. Transposed:
>
> Feature: !==
> Title: Strict Equals operator
> JavaScript: 1.3
> JScript: 5.1.5010
> ECMAScript: 3
> JSCore: 525.19
> Opera: 5.02
> KJS: 3.5.9
>
> Corrections for earlier versions of the implementations are welcome.

Seems to work in Safari 2.0 as well.

`userAgent` is:

Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/412.6.2
(KHTML, like Gecko) Safari/412.2.2

[...]

--
kangax

optimistx

unread,
Nov 11, 2009, 3:46:11 AM11/11/09
to
kangax wrote:

> Garrett Smith wrote:
...
>> Typechecking adds overhead to the code and increases call stack
>> length.
>
> Well that much is obvious :) So is every other kind of abstraction,
> doesn't it?

Good point. If the user time in looking at the page increases from
10.00000 seconds to 10.000001 seconds due to 'overhead' and
the program maintainer's time increases from 30 seconds to 40
seconds or more due to 'saving 0.000001 seconds' , which is better?
(the maintainer is not necessarily the original programmer).

When anyone is using the argument 'efficiency' would it be useful to
estimate the difference numerically?

It is true that 10.000001 seconds IS greater than 10.000000, and
it is true that 40 seconds is greater than 30 seconds,

but I think these are often extremely different matters.

David Mark

unread,
Nov 11, 2009, 5:05:03 AM11/11/09
to
On Nov 11, 3:46 am, "optimistx" <optimi...@hotmail.com> wrote:
> kangax wrote:
> > Garrett Smith wrote:
> ...
> >> Typechecking adds overhead to the code and increases call stack
> >> length.
>
> > Well that much is obvious :) So is every other kind of abstraction,
> > doesn't it?
>
> Good point. If the user time in looking at the page increases from
> 10.00000 seconds to 10.000001 seconds due to 'overhead' and
> the program maintainer's time increases from 30 seconds to 40
> seconds or more due to 'saving 0.000001 seconds' , which is better?
> (the maintainer is not necessarily the original programmer).
>

That's the problem with these libraries. They purport to save time
(e.g. on keystrokes!), but the resulting illegible code, built on ever-
shifting foundations ends up the opposite of a time-saver (i.e.
constantly in need of costly attention and upgrades).

In the case of typeof xyz == 'function' vs. an isFunction function,
the former is clearer and faster. Who knows what isFunction is (until
they look elsewhere in the code and comments?) If on looking it up, I
found it was a single typeof operation, I'd wonder why the original
author deliberately obscured its meaning, incurred performance
penalties, etc. More often, the contents of an is* function turn out
to be an ill-advised attempt to differentiate between host and native
objects (e.g. host object methods vs. native Function objects).

And don't discount the impact of function calls on performance,
especially when manipulating the DOM. Their presence (or the lack
thereof) is often critical to performance.

optimistx

unread,
Nov 11, 2009, 5:23:35 AM11/11/09
to
David Mark wrote:
...

> And don't discount the impact of function calls on performance,
> especially when manipulating the DOM. Their presence (or the lack
> thereof) is often critical to performance.
Would you like to give a couple of examples, which might oftern happen
in real life programming ?

Richard Cornford

unread,
Nov 11, 2009, 11:10:52 AM11/11/09
to
kangax wrote:
> Garrett Smith wrote:
<snip>

>> That's odd. Seems in Tracemonkey, a RegExp is callable without
>> implementing [[Call]], or ? A bug in there syntax extension, due
>> to internal typechecking for RegExp, as:
>> typeof /a/
>
> Yes, from what I remember, Mozilla makes regex objects callable
> without actually giving them [[Call]].

That would be very clear violation of ECMA 262, 3rd Ed., where Section
11.2.3 (Function Calls) features the words "If Result(3) does not
implement the internal [[Call]] method , throw a TypeError exception" as
step 5 in its algorithm. That is, in ES3 terms, if it does not have a
[[Call]] method it cannot be called, and so if it can be called it
_must_ have a [[Call]] method (or at least that is the required
behaviour, so the ability to call something has direct implications for
all other situations where the existence of a [[Call]] method is
relevant). The specifics have moved around in ES5, but the internal
IsCallable function still boils down to 'does the object have a [[Call]]
method', so nothing has really changed.

On e of the main things that has dogged the - isFunction - question over
its very long history is that very few people have been willing to state
what 'being a function' represents. If you can give a clear definition
of what 'being a function' is then you are probably in a position to
either design and effective - isFunction - method, or to declare the
determination untestable and so give up the attempt. Instead we see lots
of example of - isFunction - method that do something, get criticised
for the inconsistencies in that something, and then get changed so they
do something else, with nobody ever stating what the definition of
'Function' is that their - isFunction - is supposed to be testing.

Personally, I like a definition of 'function' that goes; "if you can
call it then it is a function". It is a definition that rules out the
viability of an - isFunction - test function (you would have to call the
object to see if it is callable, and that might have side-effects), but
it is also a very simple/obvious definition that does not introduce
issues of itself.

A (one of the many) bugbears of - isFunction - Firefox's response to:-

var x = document.createElement('OBJECT');

- which, when tested with - typeof - returns 'function'. This is seen as
incorrect, e.g.:-

<URL: http://jsninja.com/Functions#Function_Type >

The idea being that - createElement - should return an object
implementing the Element (and by implication Node) interfaces from the
W3C DOM (which is true), and that those object should not be callable
(which is an assertion that has no technical basis[1]), and therefore
that the - typeof - operation applied to such an object should not
result in 'function'.

[1] The W3C DOM is defined in terms of interfaces; sets of properties
and methods that object implementing those interfaces must possess (in
some practical sense). Neither ECMAScript, the W3C DOM specs nor the
ECMAScript bindings for the DOM interfaces place any restrictions on the
nature of the objects implementing an interface, and as ECMAScript
functions are objects there is absolutely no reason for any object
implementing a W3C DOM interface not to be an ECMAScript function. Thus
Element and Node interface implementing objects could be functions (as
could objects implementing HTMLCollection, NodeList or NamedNodeMap),
the decision is left up to the creators of the DOM providing host.

If you try to call the Firefox OBJECT element an exception is thrown,
but it is not the "x is not a function" exception that would be thrown
if the OBJECT element were not callable. The implication being that the
element is callable and the exception that is thrown is thrown within
the call. So, by a very reasonable definition of 'being a function' the
Firefox OBJECT element is a function (it can be called), and so its
resulting in 'function' when - typeof - is applied is actually a very
reasonable indicator of a truth about the nature of the object in
question.

The point being that there is no technical reason to expect to be able
to discriminate between objects implementing the Element interface (or
any other DOM specified interface) and an ECMAScript function. This
immediately brings into question the worth of having an - isFunction -
test function in the first place, especially in relation to its common
use in attempting to emulate 'method overloading' in ECMAScript. (In
fact, it brings into question the general viability of emulating 'method
overloading' in javascript, when you can only make superficial
discriminations between the types of values that are the arguments to a
function call).

The relevance for a regular expression's having, or not having, a
[[Call] method? If you cannot expect to be able to discriminate a DOM
node from a function not finding it easy to discrimination a regular
expression from a function (using - typeof - (as the specific
discrimination by duck-typing the respective object's methods/properties
is viable)) is not making things any worse.

> In WebKit, on the other hand, regex do have [[Call]] and so typeof
> returns "function", as per specs (native object + has [[Call]] ==
> "function").

<snip>


>> Many won't read the documentation of others (including pertinent
>> specifications, as witnessed recently on this NG). Developers
>> often skip right to the "what does it do" (functions, examples,
>> or tests).

I recall one of my colleagues being amused to find me reading the
SOAP/WSDL specifications prior to writing a SOAP client for our web
applications.

> It's no surprise that ES3 specs are hard to follow and full of
> ambiguities. A year ago, the only way I could understand certain
> things in specs is with the help of wonderful explanations by
> Cornford and Lasse in the archives (on related subjects).

An interesting mix of formality and informality in your choice of
identifiers there. :)

> Your last question on es-discuss proves how hard it could be to
> discern specs correctly.
>
> ES5, fortunately, takes care of some of these uncertainties.

<snip>

The ES5 spec may remove some ambiguities, but it is not going to prove
any easier for newcomers to 'get into', at least in part becasue it
introduces many new internal objects/functions that will not ease the
need to continually be going back and forth cross-refencing things.

Richard.

Peter Michaux

unread,
Nov 11, 2009, 12:06:38 PM11/11/09
to
On Nov 9, 5:02 pm, Thomas 'PointedEars' Lahn <PointedE...@web.de>
wrote:

> Peter Michaux wrote:
> > On Nov 9, 2:41 pm, Asen Bozhilov <asen.bozhi...@gmail.com> wrote:
> >> | 7.6 Identifiers
> >> | 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 believe this statement is gone from the proposed ECMAScript 5 and if so


> > I think it is good they removed it.
>
> Well, I for one do not want to see code like the following spreading around:
>
> <?php
> $bar = 'baz';
> $foo = 'bar';
> echo <<<JS
> \$foo.\$ = '{$$foo}';
> JS;
> ?>
>
> Do you?

No. I think that I would not have allowed '$' to be part of identifier
in the first place.

Peter

Thomas 'PointedEars' Lahn

unread,
Nov 11, 2009, 12:40:57 PM11/11/09
to
Peter Michaux wrote:

Then I do not understand your opinion above. A recommendation against,
as it is in Edition 3, is a step in the right direction in that sense;
a missing recommendation against, as it could be in Edition 5, is not.

David Mark

unread,
Nov 11, 2009, 12:46:20 PM11/11/09
to

Just manipulate the DOM in a loop with and without function calls.
And understand that the browser waits until an execution context is
exited before re-rendering the document. As documents get larger and
more complex, the problem becomes more apparent.

Thomas 'PointedEars' Lahn

unread,
Nov 11, 2009, 12:55:26 PM11/11/09
to
kangax wrote:

> Garrett Smith wrote:
>> That's odd. Seems in Tracemonkey, a RegExp is callable without
>> implementing [[Call]], or ? A bug in there syntax extension, due
>> to internal typechecking for RegExp, as:
>> typeof /a/

The result of the `typeof' operation has no relevance to the implementation
of the [[Call]] property of its operand.

> Yes, from what I remember, Mozilla makes regex objects callable without
> actually giving them [[Call]].

How can you possibly tell? If it does not implement [[Call]] it must throw
a TypeError, but it does not do that in TraceMonkey 1.8.1 (Iceweasel 3.5.4).
So we have to assume it does implement [[Call]].

`/x/(s)' appears to return an Array of the matches of the Regular Expression
`/x/' in the string value `s' there, as if by the expression `/x/.exec(s)'.

And no, that is _not_ "a clear violation" of ECMA-262 Ed. 3, but at least a
syntax extension supported the Specification itself. Indeed, I would like
to see it formally specified in Edition 5.

Thomas 'PointedEars' Lahn

unread,
Nov 11, 2009, 1:00:02 PM11/11/09
to
Thomas 'PointedEars' Lahn wrote:

> `/x/(s)' appears to return an Array of the matches of the Regular

> Expression `/x/' in the string value `s' [in JavaScript 1.8.1], as if by


> the expression `/x/.exec(s)'.
>
> And no, that is _not_ "a clear violation" of ECMA-262 Ed. 3, but at least
> a syntax extension supported the Specification itself. Indeed, I would
> like to see it formally specified in Edition 5.

Sorry, Richard, I misunderstood what you were saying. Full ACK now.

Garrett Smith

unread,
Nov 11, 2009, 1:25:33 PM11/11/09
to
Richard Cornford wrote:
> kangax wrote:
>> Garrett Smith wrote:
> <snip>
[...]

> A (one of the many) bugbears of - isFunction - Firefox's response to:-
>
> var x = document.createElement('OBJECT');
>
> - which, when tested with - typeof - returns 'function'. This is seen as
> incorrect, e.g.:-
>
> <URL: http://jsninja.com/Functions#Function_Type >
>

That code was reviewed here over a year ago and was changed in jQuery:

| isFunction: function( obj ) {
| return toString.call(obj) === "[object Function]";
| }

What surprises me is that wiki document was modified very recently:

# (cur) (last) 22:22, 28 September 2009 Jsninja (Talk | contribs) m
(Protected "Functions" [edit=sysop:move=sysop]) (undo)

The document also states:

| var ninja = function myNinja(){
| assert( ninja == myNinja,
| "This function is named two things - at once!" );
| };
| ninja();
| assert( typeof myNinja == "undefined",
| "But myNinja isn't defined outside of the function." );
|
| This brings up the most important point: Anonymous functions can be
| named but those names are only visible within the functions
| themselves.

That statement is true in the spec, but not in reality, and if the
example had been run in IE, that would have been realized.

This has been discussed here a lot. Juriy's NFE article goes into depth
on this as well.

Peter Michaux

unread,
Nov 11, 2009, 1:31:17 PM11/11/09
to
On Nov 11, 11:40 am, Thomas 'PointedEars' Lahn <PointedE...@web.de>
wrote:

If '$' is allowed then just allow it without any qualification or any
advice about how it should be used unless such qualification is
enforced by the language. Such wimpy advice as given in ES3 will be
and has been ignored as programmers will always do anything they can
get away with doing...so don't bother with the wimpy advice as part of
the language spec in the first place.

Imagine they had given indenting advice (e.g. four spaces, no tabs).
That would have been promptly ignored also if two spaces and tabs were
allowed.

Peter

Asen Bozhilov

unread,
Nov 11, 2009, 2:27:03 PM11/11/09
to
Richard Cornford wrote:

> If you can give a clear definition
> of what 'being a function' is then you are probably in a position to
> either design and effective - isFunction - method, or to declare the
> determination untestable and so give up the attempt.

For my `function' is `object' who [[Prototype]] and Function.prototype
referred to same `object'. If i want to test someone `object' for
`isFunction' i ever used `instanceof'.

if (f instanceof Function)
{
f.call;
f.apply;
f.dummyEnumPropertyInPrototypeChain;
}

Approach which compare internal [[Class]] property with string literal
'[object Function]'. I don't think proper name of that approach is
`isFunction' especially in browser environment, where supports cross
frame scripting.

e.g.

Function.prototype.bind = function(){};
var f = window.frames[0].f;
if (Object.prototype.toString.call(f) == '[object Function]') //true
{
f.bind(); //throw f.bind is not a function
}


Richard Cornford

unread,
Nov 11, 2009, 2:32:04 PM11/11/09
to
Peter Michaux wrote:

>On Nov 11, 11:40 am, Thomas 'PointedEars' Lahn wrote:
>> Peter Michaux wrote:
>>> Thomas 'PointedEars' Lahn wrote:
<snip>

>>>> Well, I for one do not want to see code like the following
>>>> spreading around:
<snip>

>>>> Do you?
>>
>>> No. I think that I would not have allowed '$' to be part of
>>> identifier in the first place.
>>
>> Then I do not understand your opinion above. A recommendation
>> against, as it is in Edition 3, is a step in the right
>> direction in that sense; a missing recommendation against,
>> as it could be in Edition 5, is not.
>
> If '$' is allowed then just allow it without any qualification
> or any advice about how it should be used unless such
> qualification is enforced by the language.

How do you proposes such a requirement be enforced? The javascript
engine has no way of knowing how the source code it is presented with is
generated, so know way of determining which, if any, of it has been
machine generated.

> Such wimpy advice as
> given in ES3 will be and has been ignored as programmers

If you want to call people who obviously didn't know any better
"programmers".

> will always do anything they can get away with doing.

No they won't. there is a similar injunction (equally unenforceable) in
Java, which I have never seen breached by a non-novice. It is possible
for people to perceive reasons for not doing something despite there
being nothing to stop them.

>..so don't bother with the wimpy advice as part of the language
> spec in the first place.

Because in situations where javascript source code is partly or entirely
machine generated being in a position to identify those parts of it that
were machine generated aids debugging and maintenance.

One of the issues you get with machine generated Identifiers is that it
can be difficult to predict exactly which Identifiers will be generated,
and so guaranteed that they will not collide with Identifiers already in
use in the human generated code. One way of guaranteeing no collisions
would be to provide each and every machine generated Identifier with a
prefix that was never used in human generated code. The original
ECMAScript spec made provision for that by allowing the $ symbol in
identifiers, and stated that that was the reason the symbol had been
allowed in Identifiers. It is a useful convention to follow, though may
only appear to be useful to people who have experience of mixing machine
generated javascript with human generated javascript (so likely not
novices).

> Imagine they had given indenting advice (e.g. four spaces, no
> tabs). That would have been promptly ignored also if two
> spaces and tabs were allowed.

Now indenting requirements are something that could be enforced.

Richard.

Garrett Smith

unread,
Nov 11, 2009, 2:38:58 PM11/11/09
to
Thomas 'PointedEars' Lahn wrote:
> kangax wrote:
>
>> Garrett Smith wrote:

(the example I provided was snipped).

>>> That's odd. Seems in Tracemonkey, a RegExp is callable without
>>> implementing [[Call]], or ? A bug in there syntax extension, due
>>> to internal typechecking for RegExp, as:
>>> typeof /a/
>
> The result of the `typeof' operation has no relevance to the implementation
> of the [[Call]] property of its operand.
>
>> Yes, from what I remember, Mozilla makes regex objects callable without
>> actually giving them [[Call]].
>
> How can you possibly tell? If it does not implement [[Call]] it must throw
> a TypeError, but it does not do that in TraceMonkey 1.8.1 (Iceweasel 3.5.4).
> So we have to assume it does implement [[Call]].
>

The example I provided:

| javascript: alert( Function.prototype.call.call(/a/, "a") );
| Webkit:
| elerts "a"
|
| Tracemonkey:
| TypeError: Function.prototype.call called on incompatible /a/

I'll explain why, but first Opera:
elerts "null".

That is odd, considering:
javascript: alert( /a/("a"))
Opera:
elerts "a"

The reason Function.prototype.call is used is that it requires the use
of internal [[Call]] operator.

Function.prototype.call:
| 15.3.4.4 Function.prototype.call(thisArg [ , arg1 [ , arg2, ... ] ] )
|
| The call method takes one or more arguments, thisArg and
| (optionally) arg1, arg2 etc, and performs a function call using the
| [[Call]] property of the object. If the object does not have a
| [[Call]] property, a TypeError exception is thrown. The called
| function is passed arg1, arg2, etc. as the arguments.

Read carefully this line:
| If the object does not have a [[Call]] property, a TypeError exception
| is thrown.

Function.prototype.call throws a TypeError if the object does not have a
[[Call]] property. That is exactly what happens in Tracemonkey.

Function Calls also use the [[Call]] property of the object:

| 11.2.3 Function Calls
|
| The production CallExpression : MemberExpression Arguments is
| evaluated as follows:
|
| 1. Evaluate MemberExpression.
| 2. Evaluate Arguments, producing an internal list of argument
| values (see 11.2.4).
| 3. Call GetValue(Result(1)).
| 4. If Type(Result(3)) is not Object, throw a TypeError exception.
| 5. If Result(3) does not implement the internal [[Call]] method,
| throw a TypeError exception.
| 6. [...]

In Tracemonkey, /a/() does *not* throw a TypeError in step 5.

I have no doubt that that is intentionally designed. Older versions
of Firefox, typeof /a/ resulted "function" and RegExp had been a
callable object in Firefox.

The current implementation in Tracemonkey changes that.

Probably to make different types of code work:
1) Code that typechecks methods such asl "isFunction" to return false
when passed a RegExp
2) Existing code that performs a Function Call on RegExp.
3) Code that wants to typecheck to make sure a RegExp is an Object,
possibly using a generic isObject function:

// Do not use this function
function isObject( thing ) {
return typeof thing == "object" && thing !== null;
}

In case (3) example, the typeof check expecting "object" would fail to
match a RegExp.

The result of typeof /x/ in webkit and older Firefox is "function".
The only sites that could be successfully relying on typeof /x/ ==
"object" would be IE-only sites. Public sites (that want to work in more
than two browsers) could not work using such typechecks on RegExp.

Callable RegExp in Tracemonkey and Opera is a mess. Code that doesn't
hinge heavily on typechecking isFunction or isObject should not have to
worry.

> `/x/(s)' appears to return an Array of the matches of the Regular Expression
> `/x/' in the string value `s' there, as if by the expression `/x/.exec(s)'.
>
> And no, that is _not_ "a clear violation" of ECMA-262 Ed. 3, but at least a
> syntax extension supported the Specification itself. Indeed, I would like
> to see it formally specified in Edition 5.
>

RegExp("a")("a") is a CallExpression, which is evaluated as described
in "Function Calls" which requires a TypeError be thrown if the object
does not implement [[Call]].

I can't explain what Tracemonkey and Opera do. And it doesn't matter
when typechecking is avoided (and RegExp are not called).

Thomas 'PointedEars' Lahn

unread,
Nov 11, 2009, 2:56:45 PM11/11/09
to
Garrett Smith wrote:

> Thomas 'PointedEars' Lahn wrote:
>> kangax wrote:
>>> Garrett Smith wrote:
>
> (the example I provided was snipped).

Because it was irrelevant.



>>>> That's odd. Seems in Tracemonkey, a RegExp is callable without
>>>> implementing [[Call]], or ? A bug in there syntax extension, due
>>>> to internal typechecking for RegExp, as:
>>>> typeof /a/
>>
>> The result of the `typeof' operation has no relevance to the
>> implementation of the [[Call]] property of its operand.
>>
>>> Yes, from what I remember, Mozilla makes regex objects callable without
>>> actually giving them [[Call]].
>>
>> How can you possibly tell? If it does not implement [[Call]] it must
>> throw a TypeError, but it does not do that in TraceMonkey 1.8.1
>> (Iceweasel 3.5.4). So we have to assume it does implement [[Call]].
>
> The example I provided:

Does not prove anything, which is why it still is irrelevant and has thus
been snipped.



> | javascript: alert( Function.prototype.call.call(/a/, "a") );
> | Webkit:
> | elerts "a"
> |
> | Tracemonkey:
> | TypeError: Function.prototype.call called on incompatible /a/
>

> I'll explain why, [...]

No, thanks. You do not understand what a syntax extension is to begin with.

Richard Cornford

unread,
Nov 11, 2009, 2:59:53 PM11/11/09
to
Asen Bozhilov wrote:
> Richard Cornford wrote:
>
>> If you can give a clear definition
>> of what 'being a function' is then you are probably in a position
>> to either design and effective - isFunction - method, or to declare
>> the determination untestable and so give up the attempt.
>
> For my `function' is `object' who [[Prototype]] and Function.prototype
> referred to same `object'. If i want to test someone `object' for
> `isFunction' i ever used `instanceof'.
>
> if (f instanceof Function)
> {
> f.call;
> f.apply;
> f.dummyEnumPropertyInPrototypeChain;
> }

Which demonstrates that a clear statement about what 'being a function'
means can quickly lead to a test that makes the required discrimination
(- instanceof - test precisely that relationship).

For a 'general purpose library' that definition of a function is next to
useless because objects that cannot be called are allowed to have -
Function.prototype - as their [[Prototype]] (or on their prototype
chain), so the test is easily fooled. E.G.:-

function F (){}

F.prototype = Function.prototype;

var f = new F();

alert(f instanceof Function); //alerts true, as it should

On the other hand, it is an under-appreciated fact that no specific
employment of javascript is truly 'general', so any specific test might
answer the questions that need answering in the context of its use
without needing to be generally effective. (that is, you don't write
code to fool your own tests unless you mean/want to fool them).

> Approach which compare internal [[Class]] property with string
> literal '[object Function]'. I don't think proper name of that
> approach is `isFunction' especially in browser environment,
> where supports cross frame scripting.

In ES3 terms that test has no technical basis. Host objects are allowed
to have any value as their [[Class]] property, so no predictable
relationship between the type of a host object and the outcome of
applying - Object.prototype.toString - should be expected. And, of
course, host object that are callable (so should be functions) have been
observed that do not result in '[object Function]' when that method is
applied to them (e.g. the - item - methods of collections in IE).

> e.g.
>
> Function.prototype.bind = function(){};
> var f = window.frames[0].f;
> if (Object.prototype.toString.call(f) == '[object Function]') //true
> {
> f.bind(); //throw f.bind is not a function
> }

Cross-frame/window always adds another dimension of complexity.

Richard.

Peter Michaux

unread,
Nov 11, 2009, 3:21:21 PM11/11/09
to
On Nov 11, 1:32 pm, "Richard Cornford" <Rich...@litotes.demon.co.uk>
wrote:

> Peter Michaux wrote:
> >On Nov 11, 11:40 am, Thomas 'PointedEars' Lahn wrote:
> >> Peter Michaux wrote:
> >>> Thomas 'PointedEars' Lahn wrote:
> <snip>
> >>>> Well, I for one do not want to see code like the following
> >>>> spreading around:
> <snip>
> >>>> Do you?
>
> >>> No. I think that I would not have allowed '$' to be part of
> >>> identifier in the first place.
>
> >> Then I do not understand your opinion above. A recommendation
> >> against, as it is in Edition 3, is a step in the right
> >> direction in that sense; a missing recommendation against,
> >> as it could be in Edition 5, is not.
>
> > If '$' is allowed then just allow it without any qualification
> > or any advice about how it should be used unless such
> > qualification is enforced by the language.
>
> How do you proposes such a requirement be enforced? The javascript
> engine has no way of knowing how the source code it is presented with is
> generated, so know way of determining which, if any, of it has been
> machine generated.

I don't propose such a requirement could be enforced.


> > Such wimpy advice as
> > given in ES3 will be and has been ignored as programmers
>
> If you want to call people who obviously didn't know any better
> "programmers".

If they are typing programs then I think they are programmers.


> > will always do anything they can get away with doing.
>
> No they won't. there is a similar injunction (equally unenforceable) in
> Java, which I have never seen breached by a non-novice.

If you've seen it breached by a novice then you've seen it breached.
That is all I meant. If something is allowed than someone will do it.
I didn't mean everyone will do it.


> It is possible
> for people to perceive reasons for not doing something despite there
> being nothing to stop them.
>
> >..so don't bother with the wimpy advice as part of the language
> > spec in the first place.
>
> Because in situations where javascript source code is partly or entirely
> machine generated being in a position to identify those parts of it that
> were machine generated aids debugging and maintenance.

It would be just as easy to have a convention where all identifiers
that are machine generated start with the prefix "MACHINE_GENERATED_",
for example. (Yes that example happens to be a long string.)


> One of the issues you get with machine generated Identifiers is that it
> can be difficult to predict exactly which Identifiers will be generated,
> and so guaranteed that they will not collide with Identifiers already in
> use in the human generated code. One way of guaranteeing no collisions
> would be to provide each and every machine generated Identifier with a
> prefix that was never used in human generated code. The original
> ECMAScript spec made provision for that by allowing the $ symbol in
> identifiers, and stated that that was the reason the symbol had been
> allowed in Identifiers. It is a useful convention to follow, though may
> only appear to be useful to people who have experience of mixing machine
> generated javascript with human generated javascript (so likely not
> novices).

I agree the convention may be useful. I just don't think the
convention belongs in the language specification...or if has to be in
the language specification, there shouldn't be any bible thumpers
running around telling people they are bad for doing something that is
possible.

I also don't know why there is a large worry that machine generated
code would collide namespace with human generated code. Machines can
generate and keep track of very weird identifiers no problem (e.g.
"asdfrecwe" vs "asbfrecwe"). I think two pieces of human generated
code written by different authors are far more likely to have a
namespace collision. Why not have in the spec that all identifiers
must start with your name? That is essentially the convention that has
been used in Java.


> > Imagine they had given indenting advice (e.g. four spaces, no
> > tabs). That would have been promptly ignored also if two
> > spaces and tabs were allowed.
>
> Now indenting requirements are something that could be enforced.

Yes it could be enforced. I was suggesting you imagine they had given
whitespace advice but not enforced it. Such advice would not have been
followed just like the '$' advice was not followed.

Peter

Garrett Smith

unread,
Nov 11, 2009, 4:44:48 PM11/11/09
to
Thomas 'PointedEars' Lahn wrote:
> Garrett Smith wrote:
>
>> Thomas 'PointedEars' Lahn wrote:
>>> kangax wrote:
>>>> Garrett Smith wrote:
>> (the example I provided was snipped).
>
> Because it was irrelevant.
>

So you failed to understand the relevance?

I'm not really sure what the problem is (It might be a reading and
cognition problem on your part, though stubbornness is also a
possibility.

Let me try one more time.

The point of trying Function.prototype.call on a regexp was to
investigate what happens when an object is checked to see if it has an
internal [[Call]] property.

Places where a check to see if an object implements [[Call]]:
* Function Calls
* typeof operator
* Function.prototype.call

The thread alredy discussed Function Calls and typeof operator.

I brought up Function.prototype.call. You then announced your inability
to see the relevance while simultaneously blaming me for that. SO here I
am explaining again (please do read before snipping).

An object's [[Call]] property can be accessed using a CallExpression. An
object's [[Call]] property can be indirectly
accessed using Function.prototype.call.

The example I provided uses the latter:
Function.prototype.call.call(/a/, "a");

The result in Tracemonkey (in FF 3.5) is a TypeError:


"TypeError: Function.prototype.call called on incompatible /a/"

That shows that the object does not, in fact, implement [[Call]].

That behavior could be explained by what Juriy (kangax) posted:


| Yes, from what I remember, Mozilla makes regex objects callable
| without actually giving them [[Call]].

>>>>> That's odd. Seems in Tracemonkey, a RegExp is callable without
>>>>> implementing [[Call]], or ? A bug in there syntax extension, due
>>>>> to internal typechecking for RegExp, as:
>>>>> typeof /a/
>>> The result of the `typeof' operation has no relevance to the
>>> implementation of the [[Call]] property of its operand.
>>>
>>>> Yes, from what I remember, Mozilla makes regex objects callable without
>>>> actually giving them [[Call]].
>>> How can you possibly tell? If it does not implement [[Call]] it must
>>> throw a TypeError, but it does not do that in TraceMonkey 1.8.1
>>> (Iceweasel 3.5.4). So we have to assume it does implement [[Call]].
>> The example I provided:
>
> Does not prove anything, which is why it still is irrelevant and has thus
> been snipped.
>

The example provides evidence for whether an object implement's
[[Call]].

Please do read the specification for Function.prototype.call
*carefully*.

>> | javascript: alert( Function.prototype.call.call(/a/, "a") );
>> | Webkit:
>> | elerts "a"
>> |
>> | Tracemonkey:
>> | TypeError: Function.prototype.call called on incompatible /a/
>>
>> I'll explain why, [...]
>
> No, thanks. You do not understand what a syntax extension is to begin with.
>

How convenient that you could snip what I wrote and summarily discard it
as irrelevant, with no argument whatsoever, except for the hand-waving
and condescending summation that "I don not understand what a syntax


extension is to begin with."

So lets cut the hand waving and see if there is any substance at all to
what you're writing.

Is this a syntax extension? Do you believe the () operator is overloaded
for a new type of [[RegExpCall]]?

It's possible, but not proven. I don't have much interest in proving
that to be true or false. Really, I don't care. If you do, then please
do, but don't expect me to take your word for it, just because (as you
claim) I don't understand the concept of syntax extension. Searching
bugzilla might lead to more clues.

AISB, none of this matters when typechecking is avoided (and RegExp are
not called). Since I avoid typechecking and don't call RegExp, I can
move on to real problems.

Thomas 'PointedEars' Lahn

unread,
Nov 11, 2009, 5:28:47 PM11/11/09
to
Garrett Smith wrote:

> Thomas 'PointedEars' Lahn wrote:
>> Garrett Smith wrote:
>>> Thomas 'PointedEars' Lahn wrote:
>>>> kangax wrote:
>>>>> Garrett Smith wrote:
>>> (the example I provided was snipped).
>>
>> Because it was irrelevant.
>
> So you failed to understand the relevance?

So you failed to understand the lack of its relevance.

> I'm not really sure what the problem is (It might be a reading and
> cognition problem on your part, though stubbornness is also a
> possibility.

Or, by applying Occam's razor to the situation, you could be wrong.



> Let me try one more time.

Repeating the same nonsense over and over again does not make it more true.

> The point of trying Function.prototype.call on a regexp was to
> investigate what happens when an object is checked to see if it has an
> internal [[Call]] property.

But that is _not_ the correct way to test it as far too many variables are
involved. Instead, the correct test is to call it in a /CallExpression/
with /Arguments/ and see if *that* throws a general TypeError; it does not,
it returns a value (`null' or an object reference) instead, so by all
accounts the object created by /x/ in /x/() must implement [[Call]]. That
Function.prototype.call() throws a TypeError when passed a reference to a
RegExp instance is nothing more than a peculiarity, maybe an oversight, that
can be expected of an undocumented language feature like this.

Garrett Smith

unread,
Nov 11, 2009, 6:10:20 PM11/11/09
to
Thomas 'PointedEars' Lahn wrote:
> Garrett Smith wrote:
>
>> Thomas 'PointedEars' Lahn wrote:
>>> Garrett Smith wrote:
>>>> Thomas 'PointedEars' Lahn wrote:
>>>>> kangax wrote:
>>>>>> Garrett Smith wrote:
>>>> (the example I provided was snipped).
>>> Because it was irrelevant.
>> So you failed to understand the relevance?
>
> So you failed to understand the lack of its relevance.
>

Ah, no, that would be you, and perpetually blamingme for your
inability to see what is relevant and why.

Explaining this to you starting to seem like a total waste of time.

>> I'm not really sure what the problem is (It might be a reading and
>> cognition problem on your part, though stubbornness is also a
>> possibility.
>
> Or, by applying Occam's razor to the situation, you could be wrong.
>
>> Let me try one more time.
>
> Repeating the same nonsense over and over again does not make it more true.
>
>> The point of trying Function.prototype.call on a regexp was to
>> investigate what happens when an object is checked to see if it has an
>> internal [[Call]] property.
>
> But that is _not_ the correct way to test it as far too many variables are
> involved. Instead, the correct test is to call it in a /CallExpression/
> with /Arguments/ and see if *that* throws a general TypeError; it does not,
> it returns a value (`null' or an object reference) instead, so by all
> accounts the object created by /x/ in /x/() must implement [[Call]]. That
> Function.prototype.call() throws a TypeError when passed a reference to a
> RegExp instance is nothing more than a peculiarity, maybe an oversight, that
> can be expected of an undocumented language feature like this.
>
>

You said that Function.prototype.call() throwing a TypeError when passed


a reference to a RegExp instance is nothing more than a peculiarity

That is not true. As I said, please do read the specification
*carefully*.

Again and again. One more time.

| 15.3.4.4 Function.prototype.call(thisArg [ , arg1 [ , arg2, ... ] ] )
|
| The call method takes one or more arguments, thisArg and
| (optionally) arg1, arg2 etc, and performs a function call using the
| [[Call]] property of the object. If the object does not have a
| [[Call]] property, a TypeError exception is thrown. The called
| function is passed arg1, arg2, etc. as the arguments.

One more time:


| If the object does not have a [[Call]] property, a TypeError exception
| is thrown.

Function.prototype.call.call(/a/, "a")

throws in Tracemonkey.

That behavior is relevant.

Why? The result can be explained by /a/ not having a [[Call]] property.

That is the point. Starting from "What is a function?" to "What can be
called" to "does RegExp implement [[Call]]"?

However:
/a/("a")

executes, and apparently the RegExp "/a/" appears t follow Function
Call; indeed matching teh production for CallExpression:
MemberExpression Arguments:

/a/ - MemberExpression
("a") - Arguments

So, if /a/("a") works, then why? does /a/ implement [[Call]]? We could
look to typeof which we know lies. We could try Function.prototype.call.

There really aren't any other means by which to access the internal
[[Call]] property.

kangax

unread,
Nov 12, 2009, 1:39:10 AM11/12/09
to
Richard Cornford wrote:
> kangax wrote:
>> Garrett Smith wrote:
> <snip>
>>> That's odd. Seems in Tracemonkey, a RegExp is callable without
>>> implementing [[Call]], or ? A bug in there syntax extension, due
>>> to internal typechecking for RegExp, as:
>>> typeof /a/
>>
>> Yes, from what I remember, Mozilla makes regex objects callable
>> without actually giving them [[Call]].
>
> That would be very clear violation of ECMA 262, 3rd Ed., where Section
> 11.2.3 (Function Calls) features the words "If Result(3) does not
> implement the internal [[Call]] method , throw a TypeError exception" as
> step 5 in its algorithm. That is, in ES3 terms, if it does not have a
> [[Call]] method it cannot be called, and so if it can be called it
> _must_ have a [[Call]] method (or at least that is the required
> behaviour, so the ability to call something has direct implications for
> all other situations where the existence of a [[Call]] method is
> relevant). The specifics have moved around in ES5, but the internal
> IsCallable function still boils down to 'does the object have a [[Call]]
> method', so nothing has really changed.

Yes, one way or another Mozilla's implementation comes out to be
non-conforming. If regex objects have [[Call]], then `typeof` rules are
violated; if it doesn't � function call rules are (as you have
explained). But that's the price of compatibility, and there are other
examples of spec violations like that (`ToObject` not throwing Error in
for-in, comes to mind :))

There's an old-ish Mozilla issue
https://bugzilla.mozilla.org/show_bug.cgi?id=61911 which, as I
understand, is the one responsible for making typeof regex to be
"object", not "function" as they had it before (e.g. in FF <= 2).

Looking at their patch, I can't tell if [[Class]] was removed on regex
objects or if they changed some internal `typeof` mapping (mapping of
object types to return values of `typeof`).

This whole issue was recently mentioned on es-discuss once again
(https://mail.mozilla.org/pipermail/es-discuss/2009-August/009718.html),
this time in context of `JSON.stringify`. Per specs, `JSON.stringify`
should treat values that are callable (IsCallable returns true) as
undefined. This is essentially why Function objects are ignored
during serialization.

The fun part is WebKit making regex objects callable. This makes
`JSON.stringify(/x/)` return `undefined` in WebKit, but `{}` in Firefox,
resulting in a nice cross-browser mess. Here's an involved discussion
on this topic � https://bugs.webkit.org/show_bug.cgi?id=28117.

We can blame specs and the way certain things are underspecified there.
It's not very clear if RegExp objects can implement [[Call]] as part of
allowed extension.

>
> On e of the main things that has dogged the - isFunction - question over
> its very long history is that very few people have been willing to state
> what 'being a function' represents. If you can give a clear definition
> of what 'being a function' is then you are probably in a position to
> either design and effective - isFunction - method, or to declare the
> determination untestable and so give up the attempt. Instead we see lots
> of example of - isFunction - method that do something, get criticised
> for the inconsistencies in that something, and then get changed so they
> do something else, with nobody ever stating what the definition of
> 'Function' is that their - isFunction - is supposed to be testing.

Right on point.

This is why we should teach people internals (at least some) of the
language. Understanding difference between native/host objects, and what
[[Call]] is, would make things much easier for everyone.

>
> Personally, I like a definition of 'function' that goes; "if you can
> call it then it is a function". It is a definition that rules out the
> viability of an - isFunction - test function (you would have to call the
> object to see if it is callable, and that might have side-effects), but
> it is also a very simple/obvious definition that does not introduce
> issues of itself.
>
> A (one of the many) bugbears of - isFunction - Firefox's response to:-
>
> var x = document.createElement('OBJECT');
>
> - which, when tested with - typeof - returns 'function'. This is seen as
> incorrect, e.g.:-
>
> <URL: http://jsninja.com/Functions#Function_Type >

And understanding of host objects and their unspecified nature would
completely avoid this problem.

>
> The idea being that - createElement - should return an object
> implementing the Element (and by implication Node) interfaces from the
> W3C DOM (which is true), and that those object should not be callable
> (which is an assertion that has no technical basis[1]), and therefore
> that the - typeof - operation applied to such an object should not
> result in 'function'.
>
> [1] The W3C DOM is defined in terms of interfaces; sets of properties
> and methods that object implementing those interfaces must possess (in
> some practical sense). Neither ECMAScript, the W3C DOM specs nor the
> ECMAScript bindings for the DOM interfaces place any restrictions on the
> nature of the objects implementing an interface, and as ECMAScript
> functions are objects there is absolutely no reason for any object
> implementing a W3C DOM interface not to be an ECMAScript function. Thus
> Element and Node interface implementing objects could be functions (as
> could objects implementing HTMLCollection, NodeList or NamedNodeMap),
> the decision is left up to the creators of the DOM providing host.

I have always wondered why ECMA bindings don't define property
attributes (such as those from 8.6.1 and 8.6.2).

>
> If you try to call the Firefox OBJECT element an exception is thrown,
> but it is not the "x is not a function" exception that would be thrown
> if the OBJECT element were not callable. The implication being that the
> element is callable and the exception that is thrown is thrown within
> the call. So, by a very reasonable definition of 'being a function' the
> Firefox OBJECT element is a function (it can be called), and so its
> resulting in 'function' when - typeof - is applied is actually a very
> reasonable indicator of a truth about the nature of the object in question.

Yes.

>
> The point being that there is no technical reason to expect to be able
> to discriminate between objects implementing the Element interface (or
> any other DOM specified interface) and an ECMAScript function. This
> immediately brings into question the worth of having an - isFunction -
> test function in the first place, especially in relation to its common
> use in attempting to emulate 'method overloading' in ECMAScript. (In
> fact, it brings into question the general viability of emulating 'method
> overloading' in javascript, when you can only make superficial
> discriminations between the types of values that are the arguments to a
> function call).

I find overloading to be useful when used sparingly.

Consider an interface of 2d point implementation, where setting and
retrieval of x/y properties is performed through corresponding methods.

function Point(x,y){
this.x = x;
this.y = y;
}
Point.prototype.getX = function(){
return this.x;
};
Point.prototype.setX = function(value){
this.x = value;
};

// similar getY, setY implementation

var myPoint = new Point(10, 20);

Now consider a case of "moving" a point by a certain value:

myPoint.setX(myPoint.getX() + 10);

This is perfectly fine, of course, but there's a possibility to
implement something more elegant and cleaner:

myPoint.setX(function(value){
return value + 10;
});

Valid values of `x` can only be numeric ones, so it's safe to use
overloading here:

Point.prototype.setX = function(value){
if (typeof value == "number") {
this.x = value;
}
else {
this.x = value(this.x);
}
};

// or maybe even

Point.prototype.setX = function(value){
if (typeof value == "number") {
this.x = value;
}
else {
// could recurse indefinitely if callback returns non-numeric value
this.setX(value(this.getX()));
}
};

I understand that there are alternative ways to accomplish this (such as
introducing another method).

>
> The relevance for a regular expression's having, or not having, a
> [[Call] method? If you cannot expect to be able to discriminate a DOM
> node from a function not finding it easy to discrimination a regular
> expression from a function (using - typeof - (as the specific
> discrimination by duck-typing the respective object's methods/properties
> is viable)) is not making things any worse.

isFunction can be specified to work reliably with native objects only,
but regexp having [[Call]] would still hardly matter.

It really makes sense to differentiate objects that are callable (i.e.
native, implement [[Call]], and so should return "function" on typeof)
and those that are instances of Function (have `Function.prototype` in
their prototype chain, and so can be tested with `instanceof` or
`constructor`).

Oh wait, we also have [[Class]] == "Function" :) If object is native and
has [[Class]] == "Function", it's definitely callable (as per 13.2);
however, if it's native and its [[Class]] is not "Function" it could be
callable or it could be not (as the regexp case shows, where
implementation gives [[Call]] to object with [[Class]] == "RegExp").

>
>> In WebKit, on the other hand, regex do have [[Call]] and so typeof
>> returns "function", as per specs (native object + has [[Call]] ==
>> "function").
> <snip>
>>> Many won't read the documentation of others (including pertinent
>>> specifications, as witnessed recently on this NG). Developers
>>> often skip right to the "what does it do" (functions, examples,
>>> or tests).
>
> I recall one of my colleagues being amused to find me reading the
> SOAP/WSDL specifications prior to writing a SOAP client for our web
> applications.

I noticed that not many people are fond of reading specs.

>
>> It's no surprise that ES3 specs are hard to follow and full of
>> ambiguities. A year ago, the only way I could understand certain
>> things in specs is with the help of wonderful explanations by
>> Cornford and Lasse in the archives (on related subjects).
>
> An interesting mix of formality and informality in your choice of
> identifiers there. :)

Sorry, I'll try to be consistent next time :)

>
>> Your last question on es-discuss proves how hard it could be to
>> discern specs correctly.
>>
>> ES5, fortunately, takes care of some of these uncertainties.
> <snip>
>
> The ES5 spec may remove some ambiguities, but it is not going to prove
> any easier for newcomers to 'get into', at least in part becasue it
> introduces many new internal objects/functions that will not ease the
> need to continually be going back and forth cross-refencing things.

Yes. Besides, ES5 is more or less a superset of ES3 (at least in a sense
that there's now an extra layer of deeper object properties control,
through property descriptors + array extras + JSON + strict mode).

--
kangax

kangax

unread,
Nov 12, 2009, 1:56:53 AM11/12/09
to
Garrett Smith wrote:
> Richard Cornford wrote:
>> kangax wrote:
>>> Garrett Smith wrote:
>> <snip>
> [...]
>
>> A (one of the many) bugbears of - isFunction - Firefox's response to:-
>>
>> var x = document.createElement('OBJECT');
>>
>> - which, when tested with - typeof - returns 'function'. This is seen
>> as incorrect, e.g.:-
>>
>> <URL: http://jsninja.com/Functions#Function_Type >
>>
>
> That code was reviewed here over a year ago and was changed in jQuery:
>
> | isFunction: function( obj ) {
> | return toString.call(obj) === "[object Function]";
> | }
>
> What surprises me is that wiki document was modified very recently:

Resig says that example now uses [[Class]] check.

>
> # (cur) (last) 22:22, 28 September 2009 Jsninja (Talk | contribs) m
> (Protected "Functions" [edit=sysop:move=sysop]) (undo)
>
> The document also states:
>
> | var ninja = function myNinja(){
> | assert( ninja == myNinja,
> | "This function is named two things - at once!" );
> | };
> | ninja();
> | assert( typeof myNinja == "undefined",
> | "But myNinja isn't defined outside of the function." );
> |
> | This brings up the most important point: Anonymous functions can be
> | named but those names are only visible within the functions
> | themselves.
>
> That statement is true in the spec, but not in reality, and if the
> example had been run in IE, that would have been realized.

That sentence � "This function is named two things - at once!" sounds a
bit amateur. Function is always "named" once, if we consider name to be
its Identifier (it's also what Mozilla stores in function objects'
"name" property).

What references function has little to do with its "name"; it could as
well be hundreds of various identifiers in various execution contexts.

I would also change "Anonymous functions can be named" (which sounds
weird) to "Function _expressions_ can be named, i.e. they can have
_optional identifier_".

And, of course, a very important explanation of function expressions vs.
function declarations seems to be missing there; nothing is being said
about function statements, NFE bugs and other peculiarities.

[...]

--
kangax

Lasse Reichstein Nielsen

unread,
Nov 12, 2009, 2:15:55 PM11/12/09
to
Thomas 'PointedEars' Lahn <Point...@web.de> writes:

> But that is _not_ the correct way to test it as far too many variables are
> involved. Instead, the correct test is to call it in a /CallExpression/
> with /Arguments/ and see if *that* throws a general TypeError; it does not,
> it returns a value (`null' or an object reference) instead, so by all
> accounts the object created by /x/ in /x/() must implement [[Call]].

That, or the ECMAScript implementation implements an extension that
allows using some objects without [[Call]] in call expressions in some
cases. It's really hard to say what is being extended how ... if it
even makes sense at all.

[[Call]] is a specification level detail. Implementations need not
have any concrete implementation of it. I.e., checking whether a
regexp has a [[Call]] property in an concrete implementation is
meaningless. You can at most check whether it behaves as the
specification says that objects with a [[Call]] property should.

> That Function.prototype.call() throws a TypeError when passed a
> reference to a RegExp instance is nothing more than a peculiarity,
> maybe an oversight, that can be expected of an undocumented language
> feature like this.

All you can test is how it works when used in places where the
specification expectes a [[Call]] property. For Firefox, that seems
to give different results depending on the usage (direct call vs using
Function.prototype.call, and I concur that it's likely to be an
oversight - or a deliberate "if you do that, we can't be bothered").
On other implementations (e.g., Opera) they give the same result.
Both extend the language wrt. the specification. The extensions are
not required to be explainable in terms of the specification.

/L
--
Lasse Reichstein Holst Nielsen
'Javascript frameworks is a disruptive technology'

Dr J R Stockton

unread,
Nov 12, 2009, 2:41:28 PM11/12/09
to
In comp.lang.javascript message <5PGdnYpJ6KB9vmfXnZ2dnUVZ_ohi4p2d@gigane
ws.com>, Tue, 10 Nov 2009 21:39:28, kangax <kan...@gmail.com> posted:

>I have no experience with other languages, but I still find type
>checking useful. I find it easier to read and cleaner overall to have
>`isArray(something)` rather than `typeof something.length == "number"`.
>When I read the latter one in the code, my mind still automatically

>translates it to the former one — "Oh, ok... here we're checking if
>something is array...".

In languages like Algol, Pascal, Delphi, type-checking refers at least
mainly to compile-time activity. The sine routine, for example, can
only be given as argument an integer-type or float-type literal,
variable, or expression (and the calling code will float an integer-
type); it returns a float which can only be assigned to / used as a
float.

Although input arguments can be given as literals, variables, or
expression, output arguments must be variables of the correct type.

Pointers are generally typed; a pointer-to-integer cannot point to a
float. Different types can represent the same sort of thing, for
example an integer of pounds or an integer of euros or an integer of
armadillos.

A variable on one type can be cast into a different type of the same
size, without generating run-tome code. So you can still add pounds to
euros if counting coins, with reduced risk of including any armadillos
you may have about the place.

You might find <a href="http://www.masswerk.at/algol60/report.htm">The
Algol 60 Report</a>, or the Pascal equivalent, interesting.

--
(c) John Stockton, Surrey, UK. ?@merlyn.demon.co.uk Turnpike v6.05 MIME.
Web <URL:http://www.merlyn.demon.co.uk/> - FAQish topics, acronyms, & links.
Proper <= 4-line sig. separator as above, a line exactly "-- " (SonOfRFC1036)
Do not Mail News to me. Before a reply, quote with ">" or "> " (SonOfRFC1036)

Richard Cornford

unread,
Nov 12, 2009, 8:27:32 PM11/12/09
to

Given that ECMAScript is allowed to have 'extensions', I have been
wondering if what Mozilla is doing can be put across as an 'extension'
of some sort. Two parts of the (3rd Ed.) spec talk about 'extensions'
(what is, or is not, allowed); Section 16 (Errors) and Section 2
(Conformance),.

Section 2 states that; "A conforming implementation of ECMAScript is
permitted to support program and regular expression syntax not described
in this specification." So is allowing a regular expression to be called
even if it does not have a [[Call]] method a 'syntax extension'? I
don't see how it can be, as the syntax of a function call is unchanged
even when applied to regular expressions (in pure (non-extended)
ECMAScript calling a regular expression is not a syntax error, even if
it can be expected to result in a runtime error if executed). Or at
least, in this form:-

var x = /a/g;
var y = x('a');

- there is no syntax error anD no deviation from the specified syntax.
However:-

var y = /a/g('a');

- is a bit more problematic in ES3. We start at the syntax for Function
Call (11.2.3):-

CallExpression : MemberExpression Arguments

- and then have to examine MemberExpression (11.2)-

MemberExpression :
PrimaryExpression
FunctionExpression
MemberExpression [ Expression ]
MemberExpression . Identifier
new MemberExpression Arguments

- where we are expecting PrimaryExpression to be pertinent, so to
section 11.1:-

PrimaryExpression :
this
Identifier
Literal
ArrayLiteral
ObjectLiteral
( Expression )

In is the inclusion of Identifier in the PrimaryExpression list that
allows the first form of the syntax above, and guarantees that the
language's syntax cannot prevent a call to a regular expression.(at
least if you don't look too hard at the right hand side of the
assignment production and realise that ES3 makes no assertion about a
regular expression literal being an Expression of any sort). We might
expect the RegularExpressionLiteral to be in the list for Literal
(section 7.8):-

Literal ::
NullLiteral
BooleanLiteral
NumericLiteral
StringLiteral

- but it is not. ES5 fixes this by adding RegularExpressionLiteral to
the end of the list for Literal.

In any event, either it is a syntax error to use a
RegularExpressionLiteral at any point in an ES3 Program, or ES3 syntax
allows them to be called (in the sense of allowing them to be the
operand of the 'call operator', that is, it allows you to try to call
them in the same way as it allows you to call an Array or an object) and
so an ability to call them is not a 'syntax extension'.

The "Conformance" section (2) also states that: "A conforming
implementation of ECMAScript must provide and support all the types,
values, objects, properties, functions, and program syntax and semantics
described in this specification.", which means that you cannot change
the meaning of a function call (that would be failing to follow the
semantics of the specification. A (successful) function call means
executing the [[Call]] method of a callable object. Which boils down to;
'If you can call it, it must have a [[Call]] method' (or 'if you can
call it, it must behave as if it has a [[Call]] method').

Section 16 states that "An implementation may provide additional types,
values, objects, properties, and functions beyond those described in
this specification.", and Section 2 says; "A conforming implementation
of ECMAScript is permitted to provide additional types, values, objects,
properties, and functions beyond those described in this specification.
In particular, a conforming implementation of ECMAScript is permitted to
provide properties not described in this specification, and values for
those properties, for objects that are described in this specification."

A provision to provide additional properties may be used to justify a
regular expression having additional properties, such as a [[Call]]
internal property in addition to those laid out in the spec. Thus a
callable regular expression seems to be allowed by the specification.

> If regex objects have [[Call]],

Which I think the spec would allow.

> then `typeof` rules are violated;

There is the one I don't see any way around. Regular expressions are
allowed to be callable _because_ they are allowed to have a [[Call]]
property in addition to those laid out in the spec, but if they do have
a [[Call]] method they should produce 'function' if tested with -
typeof - (and be subject to Function.prototype.call/apply.call/apply -).

> if it doesn't � function call rules are (as you have
> explained). But that's the price of compatibility, and there are
> other examples of spec violations like that (`ToObject` not
> throwing Error in for-in, comes to mind :))

That one is not a price of compatibility because for many years
JavaScript(tm) regular expressions have been callable and have been
reporting themselves as 'function' if tested with - typeof -. Any price
this is extorting is the price of more or less ignorant web developers
insisting that what they believe should be the case become the case,
despite the consequences.

> There's an old-ish Mozilla issue
> https://bugzilla.mozilla.org/show_bug.cgi?id=61911 which,
> as I understand, is the one responsible for making typeof
> regex to be "object", not "function" as they had it before
> (e.g. in FF <= 2).

And you notice that the primarily complaint for the bug is somewhere
between technically inaccurate and plain wrong.

> Looking at their patch, I can't tell if [[Class]] was removed

[[Call]]?

> on regex objects or if they changed some internal `typeof`
> mapping (mapping of object types to return values of `typeof`).
>
> This whole issue was recently mentioned on es-discuss once
> again
> (https://mail.mozilla.org/pipermail/es-discuss/2009-August/009718.html),
> this time in context of `JSON.stringify`. Per specs,
> `JSON.stringify` should treat values that are callable (IsCallable
> returns true) as undefined. This is essentially why Function
> objects are ignored during serialization.
>
> The fun part is WebKit making regex objects callable. This makes
> `JSON.stringify(/x/)` return `undefined` in WebKit, but `{}` in
> Firefox,
> resulting in a nice cross-browser mess. Here's an involved discussion
> on this topic � https://bugs.webkit.org/show_bug.cgi?id=28117.
>
> We can blame specs and the way certain things are underspecified
> there. It's not very clear if RegExp objects can implement [[Call]] as
> part of allowed extension.

I think they can, but I don't think that there is any way to avoid the
consequences without violating something.

But avoid the problem how? Presumably by triggering the realization that
the general task of identifying some sort of 'type' by examining an
arbitrary value is unsolvable, leading to the realization that code
design should not then be predicated on the ability to derive types from
arbitrary values.

That is not going to be a welcome realization for someone who has
already published/distributed/employed an API predicated on the
expectation of being able to do just that.

>> The idea being that - createElement - should return an object
>> implementing the Element (and by implication Node) interfaces
>> from the W3C DOM (which is true), and that those object should
>> not be callable (which is an assertion that has no technical
>> basis[1]), and therefore that the - typeof - operation applied
>> to such an object should not result in 'function'.
>>
>> [1] The W3C DOM is defined in terms of interfaces; sets of
>> properties and methods that object implementing those interfaces
>> must possess (in some practical sense). Neither ECMAScript, the
>> W3C DOM specs nor the ECMAScript bindings for the DOM interfaces
>> place any restrictions on the nature of the objects implementing
>> an interface, and as ECMAScript functions are objects there is
>> absolutely no reason for any object implementing a W3C DOM interface
>> not to be an ECMAScript function. Thus Element and Node
>> interface implementing objects could be functions (as could objects
>> implementing HTMLCollection, NodeList or NamedNodeMap), the decision
>> is left up to the creators of the DOM providing
>> host.
>
> I have always wondered why ECMA bindings don't define property
> attributes (such as those from 8.6.1 and 8.6.2).

When a DOM property is stated as read-only (and that restriction is
implemented) then it is reasonable to assume that ECMAScript -
ReadOnly - attribute does apply. Other characteristics of such object's;
enumerability, general mutability, etc. are not really the
responsibility/concern of the W3C interfaces.

But in any event, remember that the W3C does not employ people with a
good understanding of ECMAScript and/or browser scripting to work on
their APIs, so they are bound to always botch something.

>> If you try to call the Firefox OBJECT element an exception is
>> thrown, but it is not the "x is not a function" exception that
>> would be thrown if the OBJECT element were not callable. The
>> implication being that the element is callable and the exception
>> that is thrown is thrown within the call. So, by a very reasonable
>> definition of 'being a function' the Firefox OBJECT element is a
>> function (it can be called), and so its resulting in 'function'
>> when - typeof - is applied is actually a very reasonable
>> indicator of a truth about the nature of the object in question.
>
> Yes.
>
>> The point being that there is no technical reason to expect to
>> be able to discriminate between objects implementing the Element
>> interface (or any other DOM specified interface) and an ECMAScript
>> function. This immediately brings into question the worth of
>> having an - isFunction - test function in the first place,
>> especially in relation to its common use in attempting to emulate
>> 'method overloading' in ECMAScript. (In fact, it brings into
>> question the general viability of emulating 'method overloading'
>> in javascript, when you can only make superficial discriminations
>> between the types of values that are the arguments
>> to a function call).
>
> I find overloading to be useful when used sparingly.

I find method overloading useful. Not when used sparingly (as my sparing
use of it is a consequence of its very limited viability) but when used
selectively. That is, I am only going to attempt to discriminate between
value types when I know enough about the possible range of values to be
certain that the discrimination test can tell me what I need to know.

> Consider an interface of 2d point implementation, where setting
> and retrieval of x/y properties is performed through corresponding
> methods.
>
> function Point(x,y){
> this.x = x;
> this.y = y;
> }
> Point.prototype.getX = function(){
> return this.x;
> };
> Point.prototype.setX = function(value){
> this.x = value;
> };
>
> // similar getY, setY implementation
>
> var myPoint = new Point(10, 20);
>
> Now consider a case of "moving" a point by a certain value:
>
> myPoint.setX(myPoint.getX() + 10);
>
> This is perfectly fine, of course, but there's a possibility to
> implement something more elegant and cleaner:
>
> myPoint.setX(function(value){
> return value + 10;
> });

There are a couple of subjective judgments in that's being "more elegant
and cleaner", but that is not important here.

> Valid values of `x` can only be numeric ones, so it's safe to use
> overloading here:
>
> Point.prototype.setX = function(value){
> if (typeof value == "number") {
> this.x = value;
> }
> else {
> this.x = value(this.x);
> }
> };

So there is effectively a contract in the API which states that the
values passed into the method may only be numeric primitives or
functions that are passed a numeric argument and return a numeric
result. Which is a completely valid and viable approach to having some
form of 'method overloading' while avoiding the insolvability of the
type identification problem in the general case (and is pretty much
exactly what I would do (internal detail and notion of 'elegance'
aside)).

<snip>


> I understand that there are alternative ways to accomplish this
> (such as introducing another method).

Where introducing another method is perfectly valid as with the
'overloading' you have it is necessary for the programmer to be aware of
the types being passed as arguments at the point of calling the method,
and so knowing the type could then know which method to use with that
type.

>> The relevance for a regular expression's having, or not having,
>> a [[Call] method? If you cannot expect to be able to discriminate
>> a DOM node from a function not finding it easy to discrimination
>> a regular expression from a function (using - typeof - (as the
>> specific discrimination by duck-typing the respective object's
>> methods/properties is viable)) is not making things any worse.
>
> isFunction can be specified to work reliably with native objects
> only, but regexp having [[Call]] would still hardly matter.

Yes, one of the ways of avoiding the general type identification problem
is to constrain the range of possible valid values. It is quite
reasonable, so long as you define the expected behavior/ argument ranges
for - isFunction - in advance.

> It really makes sense to differentiate objects that are callable
> (i.e. native, implement [[Call]], and so should return "function"
> on typeof) and those that are instances of Function (have
> `Function.prototype` in their prototype chain, and so can be
> tested with `instanceof` or `constructor`).

That probably depends a bit on the context. If you can guarantee that
the system will not contain any objects that are not callable but still
inherit from - Function.prototype - then there is no reason for trying
to discriminate between those non-existent objects and any others.

> Oh wait, we also have [[Class]] == "Function" :) If object is native
> and has [[Class]] == "Function", it's definitely callable
> (as per 13.2); however, if it's native and its [[Class]] is not
> "Function" it could be callable or it could be not (as the
> regexp case shows, where implementation gives [[Call]] to object
> with [[Class]] == "RegExp").

Yes, and a definition of 'being a function' that says a 'function' is
only any native function (all host objects/methods and unexpectedly
callable objects are then not what we are calling a 'function') is at
least a workable definition.

>>> In WebKit, on the other hand, regex do have [[Call]] and so
>>> typeof returns "function", as per specs (native object + has
>>> [[Call]] == "function").
>> <snip>
>>>> Many won't read the documentation of others (including pertinent
>>>> specifications, as witnessed recently on this NG). Developers
>>>> often skip right to the "what does it do" (functions, examples,
>>>> or tests).
>>
>> I recall one of my colleagues being amused to find me reading
>> the SOAP/WSDL specifications prior to writing a SOAP client for
>> our web applications.
>
> I noticed that not many people are fond of reading specs.

<snip>

Many people are not fond of paying taxes.

Richard.

Garrett Smith

unread,
Nov 12, 2009, 9:36:50 PM11/12/09
to

| A conforming implementation of ECMAScript is permitted to provide


| additional types, values, objects, properties

A [[Call]] property would be an additional property. It would also be
against what seems to be an intention of the specification as:

Additional properties. [[Call]] is an internal property. I believe this
is allowed.

The spec hints in a few places about callable built-ins that are not
functions, but doesn't name one.

Take section 15:
| Unless specified otherwise, the [[Class]] property of a built-in
| object is "Function" if that built-in object has a [[Call]] property,
| or "Object" if that built-in object does not have a [[Call]] property.

Which seems to indicate that there is some sort of built-in, callable.
Where?

and:

| The global object does not have a [[Call]] property; it is not
| possible to invoke the global object as a function.

Why even mention that? It would not be expected, and it is not mentioned
for any other object, e.g. "Array instances do not have [[Call]]
property." The only reason I can see for mentioning it is that it is
something they wanted to allow. As if to let an implementation make
something, RegExp, maybe, callable.

I was wondering when someone would mention that.

I asserted earlier that a RegularExpressionLiteral was a
MemberExpression but nobody called me on that.

Likewise with:

/a/.test("a");

- where the RegularExpressionLiteral is handled as a MemberExpression.

> In any event, either it is a syntax error to use a
> RegularExpressionLiteral at any point in an ES3 Program,

It is an understated shortcoming in the specification.

[...]

kangax

unread,
Nov 15, 2009, 11:15:41 PM11/15/09
to
Richard Cornford wrote:
> kangax wrote:
[...]

Interesting. It hasn't occurred to me to check syntactic conformance of
callable regex literals.

[...]

>> if it doesn't � function call rules are (as you have
>> explained). But that's the price of compatibility, and there are
>> other examples of spec violations like that (`ToObject` not
>> throwing Error in for-in, comes to mind :))
>
> That one is not a price of compatibility because for many years
> JavaScript(tm) regular expressions have been callable and have been
> reporting themselves as 'function' if tested with - typeof -. Any price
> this is extorting is the price of more or less ignorant web developers
> insisting that what they believe should be the case become the case,
> despite the consequences.

I don't know the whole story there, but I was basing my assumptions on
Brendan's comments to this whole "situation". To cite one
(https://bugs.webkit.org/show_bug.cgi?id=28117#c21)

"[...]
We fixed the higher-numbered one first, making typeof /a/ == "function".
But then we retreated in 61911 due to complaints and (I seem to recall;
it's hard to find evidence at the moment) real web compatibility problems.

The complaints weren't all from spec-purists who did not like the
extension in SpiderMonkey that allows /a/(s) as shorthand for
/a/.exec(s). I remember more than a few places where real code was
flummoxed by typeof /a/ == "function". This confusing result broke code,
whether or not such code expected (this would have been Mozilla-specific
code, originally) to be able to call a regexp as shorthand for exec'ing it.

Anyway, we threw in the towel with the resolution of 61911. The only
further retreat for us is to remove callability, but that may be hard.
We may be stuck. We can't easily go back to typeof /a/ == "function", in
any event.

/be"

Is it only complains of incompetent web developers that triggered this
change? I don't know. It certainly looks like there could be more to it
(e.g. incompetent legacy scripts, which should still be supported ;))

[...]

>> Looking at their patch, I can't tell if [[Class]] was removed
>
> [[Call]]?

Yep.

[...]

>>> Personally, I like a definition of 'function' that goes; "if you
>>> can call it then it is a function". It is a definition that rules
>>> out the viability of an - isFunction - test function (you would
>>> have to call the object to see if it is callable, and that might
>>> have side-effects), but it is also a very simple/obvious definition
>>> that does not introduce issues of itself.
>>>
>>> A (one of the many) bugbears of - isFunction - Firefox's response
>>> to:-
>>>
>>> var x = document.createElement('OBJECT');
>>>
>>> - which, when tested with - typeof - returns 'function'. This is
>>> seen as incorrect, e.g.:-
>>>
>>> <URL: http://jsninja.com/Functions#Function_Type >
>>
>> And understanding of host objects and their unspecified nature
>> would completely avoid this problem.
>
> But avoid the problem how? Presumably by triggering the realization that
> the general task of identifying some sort of 'type' by examining an
> arbitrary value is unsolvable, leading to the realization that code
> design should not then be predicated on the ability to derive types from
> arbitrary values.

Understanding the nature of host objects would avoid never ending
patching of type-checking utility to account for cases that can
inherently take any form.

Yes, it appears to be so.

>
> But in any event, remember that the W3C does not employ people with a
> good understanding of ECMAScript and/or browser scripting to work on
> their APIs, so they are bound to always botch something.

Ok :)

[...]

> <snip>
>> I understand that there are alternative ways to accomplish this
>> (such as introducing another method).
>
> Where introducing another method is perfectly valid as with the
> 'overloading' you have it is necessary for the programmer to be aware of
> the types being passed as arguments at the point of calling the method,
> and so knowing the type could then know which method to use with that
> type.

And I'm not sure which one makes for a more convenient/intuitive API
design. It seems that adding another method in situation like this could
actually result in a more understandable code; method name could hint at
method's semantics, whereas overloading could lead to ambiguity.

[...]

>> Oh wait, we also have [[Class]] == "Function" :) If object is native
>> and has [[Class]] == "Function", it's definitely callable
>> (as per 13.2); however, if it's native and its [[Class]] is not
>> "Function" it could be callable or it could be not (as the
>> regexp case shows, where implementation gives [[Call]] to object
>> with [[Class]] == "RegExp").
>
> Yes, and a definition of 'being a function' that says a 'function' is
> only any native function (all host objects/methods and unexpectedly
> callable objects are then not what we are calling a 'function') is at
> least a workable definition.

Which is why testing object for [[Class]] == "Function" is a
more-or-less "viable" solution for isFunction utility, as long as
isFunction defines function to be a Function object.

This is practically an alternative to instanceof check, but the one
that's cross-frame -safe. Instead of asserting that something is a
Function object by checking if `Function.prototype` is in its prototype
chain, we check if its [[Class]] has a "Function" value.

There are, of course, other implications here that make this
"alternative" so much different that instanceof check � possibility of
host objects implementing [[Class]] == "Function" (and so resulting in
false positives) or IE's wrapping of cross-window objects (and so giving
false positives once again).

In any case, the more important question to ask here is what exactly it
is that needs to be done with an object which requires to know whether
it is a function. When this question is asked, the solution usually
becomes much more apparent and viable.

[...]

--
kangax

Garrett Smith

unread,
Nov 16, 2009, 3:34:40 AM11/16/09
to
Richard Cornford wrote:
> kangax wrote:
>> Richard Cornford wrote:
>>> kangax wrote:
>>>> Garrett Smith wrote:
>>> <snip>

[snip]

>> I have always wondered why ECMA bindings don't define property
>> attributes (such as those from 8.6.1 and 8.6.2).
>
> When a DOM property is stated as read-only (and that restriction is
> implemented) then it is reasonable to assume that ECMAScript -
> ReadOnly - attribute does apply. Other characteristics of such object's;
> enumerability, general mutability, etc. are not really the
> responsibility/concern of the W3C interfaces.
>

It is not always the case that a DOM readonly is implemented (in
ECMAScript, in a browser) as ReadOnly.

A DOM readonly attribute may be implemented with a getter but no setter.
The result is not silent failure (as would be the case if it were
implemented as ECMASCript {ReadOnly}, but an error, as seen in Firefox,
where, for example, a MouseEvent has a readonly "clientX" property that
is implemented as a getter (with no setter, resulting in error when
attempting to set the property).

Example:
javascript: void(document.onclick=function c(e){alert(e.clientX=12);});

Result:
Error: setting a property that has only a getter

> But in any event, remember that the W3C does not employ people with a
> good understanding of ECMAScript and/or browser scripting to work on
> their APIs, so they are bound to always botch something.
>

Why do you think that is?

Richard Cornford

unread,
Nov 16, 2009, 2:01:09 PM11/16/09
to
On Nov 16, 4:15 am, kangax wrote:
> Richard Cornford wrote:
>> kangax wrote:
> [...]
>>> Yes, one way or another Mozilla's implementation comes
>>> out to be non-conforming.
>
>> Given that ECMAScript is allowed to have 'extensions', I have
>> been wondering if what Mozilla is doing can be put across as
>> an 'extension' of some sort. ...
<snip>
>>> if it doesn't — function call rules are (as you have

That does appear to be what he was saying. His "spec-purists" were
(arguably) wrong, and a callable regular expression is an allowable
language extension, so there complaints could be dismissed, but the
authors of "real code [that] was flummoxed by typeof /a/ ==
"function"" seem to fall straight into my "ignorant web developers


insisting that what they believe should be the case become the

case, ... " as they have no grounds for expecting to be able to
differentiate regular expressions from object with - typeof -
'function' (and testing in a range of browsers would have given them
empirical evidence of not being able to do so in practice).

> I don't know. It certainly looks like there could be more to it
> (e.g. incompetent legacy scripts, which should still be
> supported ;))

Where by "incompetent legacy scripts" you mean scripts that were
authored without any testing on JavaScript(tm)?

<snip>


>>> And understanding of host objects and their unspecified nature
>>> would completely avoid this problem.
>
>> But avoid the problem how? Presumably by triggering the realization
>> that the general task of identifying some sort of 'type' by
>> examining an arbitrary value is unsolvable, leading to the
>> realization that code design should not then be predicated on
>> the ability to derive types from arbitrary values.
>
> Understanding the nature of host objects would avoid never
> ending patching of type-checking utility to account for cases
> that can inherently take any form.

So the code design is changed to avoid type-checking?

<snip>


>> <snip>
>>> I understand that there are alternative ways to accomplish
>>> this (such as introducing another method).
>
>> Where introducing another method is perfectly valid as with
>> the 'overloading' you have it is necessary for the programmer
>> to be aware of the types being passed as arguments at the point
>> of calling the method, and so knowing the type could then know
>> which method to use with that type.
>
> And I'm not sure which one makes for a more convenient/intuitive
> API design.

I am; it would be the multi-method approach. You don't end up with
significantly more code, just more function objects (which get to
execute quicker because they no longer need to examine the types of
their arguments).

> It seems that adding another method in situation like this could
> actually result in a more understandable code; method name could
> hint at method's semantics, whereas overloading could lead to
> ambiguity.

There are people who would put a 'does' in place of your 'could'.

> [...]
>
>>> Oh wait, we also have [[Class]] == "Function" :) If object is
>>> native and has [[Class]] == "Function", it's definitely
>>> callable (as per 13.2); however, if it's native and its
>>> [[Class]] is not "Function" it could be callable or it
>>> could be not (as the regexp case shows, where implementation
>>> gives [[Call]] to object with [[Class]] == "RegExp").
>
>> Yes, and a definition of 'being a function' that says a
>> 'function' is only any native function (all host objects/methods
>> and unexpectedly callable objects are then not what we are
>> calling a 'function') is at least a workable definition.
>
> Which is why testing object for [[Class]] == "Function" is a
> more-or-less "viable" solution for isFunction utility, as long as
> isFunction defines function to be a Function object.

So long as - isFunction - defines host objects as being un-decidable
cases that should never be presented as arguments. (So the person
writing the code that calls - isFunction - is already expected to know
enough about the object to be certain that it is not a host object.)

> This is practically an alternative to instanceof check, but
> the one that's cross-frame -safe. Instead of asserting that
> something is a Function object by checking if
> `Function.prototype` is in its prototype chain, we check if
> its [[Class]] has a "Function" value.

But in the event that you have a single page situation and know that
you will not be creating/testing objects that are not callable but
inherit from - Function.prototype - then each test is as good as the
other.

> There are, of course, other implications here that make this

> "alternative" so much different that instanceof check — possibility


> of host objects implementing [[Class]] == "Function"

Is there any reason a host object could not have - Function.prototype
- on its prototype chain? I cannot see one, so these two tests are
equivalent in their inability to predictably handle host objects.

> (and so resulting in false positives) or IE's wrapping of
> cross-window objects (and so giving false positives once again).

I think the IE cross-windows stuff is more likely to result in a false
negative (as it means that (at least some) native and built-in
functions will report 'object' if tested with - typeof - by code in
another window).

> In any case, the more important question to ask here is what
> exactly it is that needs to be done with an object which
> requires to know whether it is a function. When this question
> is asked, the solution usually becomes much more apparent and
> viable.

Knowing (being able to clearly state) the discrimination you need to
make in context is the viable alternative to knowing what you mean by
'being a function'. There is nothing wrong with coming at the problem
form the other direction, but the resulting test function certainly
should not be called 'isFunction'.

Richard.

Garrett Smith

unread,
Nov 24, 2009, 6:44:04 PM11/24/09
to
kangax wrote:
> Richard Cornford wrote:
>> kangax wrote:


[...]

>>


>> But in any event, remember that the W3C does not employ people with a
>> good understanding of ECMAScript and/or browser scripting to work on
>> their APIs, so they are bound to always botch something.
>
> Ok :)
>

Couldn't be more true. The w3c employees have a strong aversion to
learning ECMAScript. Take this in my inbox:


| On Sat, Nov 7, 2009 at 12:53 PM, Charles McCathieNevile
| <cha...@opera.com> wrote:
| > Sorry folks, it was a long meeting for me so this was delayed.
| >
| > The draft minutes are included at
| > http://www.w3.org/2009/11/02-webapps-minutes.html starting from the
| WebIDL
| > section - http://www.w3.org/2009/11/02-webapps-minutes.html#item06
| >

Reading the discussion there, I see:

| JS: need to define what exactly a seqnece is
|
| SW: sequence is a JS array, array is a host object
|
| <weinig> http://dev.w3.org/2006/webapi/WebIDL/#es-sequence
|
| SW: NodeList seems to map closer to array
|
| JS: NodeList is readonly, so can't be a simple JS-array
|
| NM: is anyone actually using Array?
| ... crickets...
|
| SW: don't know of any specs that use it. Maybe NodeList could be
| expressed
| as an Array... might not be worth putting Array in v1 if no one is
| using it

The people who are designing the APIs for web browser scripting lack a
very basic, fundamental understanding of the technologies for which they
are designing APIs.

I've replied to that message but it did not make it through to the list.

Philippe Le Hegaret, Art Barstow, Mike Smith, Charles McCathieNevile,
and Doug Schepers decided to revoke my posting because I used the word
"Misguided"[1], plus some false information pertaining to me, used to
justify that action.

I have also received personal email messages from Mr Doug Schepers that
were between nasty and rediculous (sort of insane). I also received some
flippant remarks on list (apparently Mr Schepers has a personal issue).

Nokia is vying very hard to get their completed API approved by the w3c.
There is considerable amount of money to be made by marketing a multi
touch aware device plus browser. For details, please see the pile of
shit called "iPhone".

[1]http://lists.w3.org/Archives/Public/public-webapps/2009OctDec/0182.html

Garrett Smith

unread,
Nov 25, 2009, 3:29:52 PM11/25/09
to
kangax wrote:
> Garrett Smith wrote:
>> Richard Cornford wrote:
>>> kangax wrote:
>>>> Garrett Smith wrote:
>>> <snip>
>> [...]
>>
>>> A (one of the many) bugbears of - isFunction - Firefox's response to:-
>>>
>>> var x = document.createElement('OBJECT');
>>>
>>> - which, when tested with - typeof - returns 'function'. This is seen
>>> as incorrect, e.g.:-
>>>
>>> <URL: http://jsninja.com/Functions#Function_Type >
>>>
>>
>> That code was reviewed here over a year ago and was changed in jQuery:
>>
>> | isFunction: function( obj ) {
>> | return toString.call(obj) === "[object Function]";
>> | }
>>
>> What surprises me is that wiki document was modified very recently:
>
> Resig says that example now uses [[Class]] check.
>

Then he is mistaken. The site has the same code:
http://jsninja.com/Functions#Function_Type

// Do not use this function:

| function isFunction( fn ) {
| return !!fn && !fn.nodeName && fn.constructor != String &&
| fn.constructor != RegExp && fn.constructor != Array &&
| /function/i.test( fn + "" );
| }

Nobody should be using that code at this time. That isFunction relies on
function decompilation. It fails across frames. It provides wrong
results for some cases, the most obvious being any object whose toString
contains substring "function" (any case).

var book = {
title : "functional javascript",
valueOf : function(){ return this.title; }
};

That isFunction will result true.

The justification for that function is based on the method overloading
strategies used in the initial design of jQuery.

We've been over and over this. I blogged about it with many examples, in
2007. That lousy function has gotten a lot of criticism. It seems hard
to believe that Resig could be unaware of that criticism.

So why is he writing about it advocating its use? Making a one-time
mistake is understandable. Advocating the use a well-known mistake
defies explanation.

Garrett Smith

unread,
Nov 27, 2009, 2:05:07 PM11/27/09
to
Garrett Smith wrote:
> kangax wrote:
>> Richard Cornford wrote:
>>> kangax wrote:
>
>
> [...]
>
>>>
>>> But in any event, remember that the W3C does not employ people with a
>>> good understanding of ECMAScript and/or browser scripting to work on
>>> their APIs, so they are bound to always botch something.
>>
>> Ok :)
>>
>
> Couldn't be more true. The w3c employees have a strong aversion to
> learning ECMAScript.
[snip]

The paying members to the w3c are not any better.

Take Travis Leithead, Microsoft's Program Manager and Expert, trying to
learn javascript from about.com while writing articles that show his
misunderstanding of the language.

http://www.w3.org/2009/09/23-webapps-minutes.html
| TL: looking at a JS/unicode site. /u is supported natively in JS
|
| <Travis> http://javascript.about.com/library/blunicode.htm

Travis tries to explain javascript inheritance, full of misiformation:
http://msdn.microsoft.com/en-us/library/dd282900%28VS.85%29.aspx

He (they) also proposed dropping currentStyle/runtimeStyle:
http://www.pubbs.net/web/200909/112588/

Amazing. It's as if someone sat down and said, "Guys, how can we
/really/ the web so that sites won't work in IE?".

Thomas 'PointedEars' Lahn

unread,
Nov 28, 2009, 10:38:47 PM11/28/09
to
Richard Cornford wrote:

> Given that ECMAScript is allowed to have 'extensions', I have been
> wondering if what Mozilla is doing can be put across as an 'extension'
> of some sort. Two parts of the (3rd Ed.) spec talk about 'extensions'
> (what is, or is not, allowed); Section 16 (Errors) and Section 2
> (Conformance),.
>
> Section 2 states that; "A conforming implementation of ECMAScript is
> permitted to support program and regular expression syntax not described
> in this specification." So is allowing a regular expression to be called
> even if it does not have a [[Call]] method a 'syntax extension'? I
> don't see how it can be, as the syntax of a function call is unchanged
> even when applied to regular expressions (in pure (non-extended)
> ECMAScript calling a regular expression is not a syntax error, even if
> it can be expected to result in a runtime error if executed). Or at
> least, in this form:-
>
> var x = /a/g;
> var y = x('a');
>
> - there is no syntax error anD no deviation from the specified syntax.

ACK.

ISTM that, while trying to find an explanation for the observed behavior in
the syntactical grammar, you are overlooking the constraints of the lexical
grammar here (ES3F, 5.1.2). RegExp literals are produced by another goal
symbol than other source code, /InputElementRegExp/. Therefore, in a
strictly conforming implementation of ECMAScript Edition 3,

var y = /a/g('a');

could not be produced by /VariableStatement/ because `/a/g' must be produced
by /RegularExpressionLiteral/ which would leave only "('a')", a syntax error
there, and the /Identifier/ production would not apply (/Expression/ would
apply, but a /PrimaryExpression/ were not allowed in this context).

> We might expect the RegularExpressionLiteral to be in the list for Literal
> (section 7.8):-
>
> Literal ::
> NullLiteral
> BooleanLiteral
> NumericLiteral
> StringLiteral
>
> - but it is not. ES5 fixes this by adding RegularExpressionLiteral to
> the end of the list for Literal.

And, AISB, newer JavaScript versions appear to implement that.

kangax

unread,
Nov 29, 2009, 11:45:53 PM11/29/09
to
Garrett Smith wrote:
> kangax wrote:
>> Garrett Smith wrote:
>>> Richard Cornford wrote:
>>>> kangax wrote:
>>>>> Garrett Smith wrote:
>>>> <snip>
>>> [...]
>>>
>>>> A (one of the many) bugbears of - isFunction - Firefox's response to:-
>>>>
>>>> var x = document.createElement('OBJECT');
>>>>
>>>> - which, when tested with - typeof - returns 'function'. This is
>>>> seen as incorrect, e.g.:-
>>>>
>>>> <URL: http://jsninja.com/Functions#Function_Type >
>>>>
>>>
>>> That code was reviewed here over a year ago and was changed in jQuery:
>>>
>>> | isFunction: function( obj ) {
>>> | return toString.call(obj) === "[object Function]";
>>> | }
>>>
>>> What surprises me is that wiki document was modified very recently:
>>
>> Resig says that example now uses [[Class]] check.
>>
>
> Then he is mistaken. The site has the same code:

How is he mistaken? The section *now uses* [[Class]] check (as Resig
said). I guess that wiki is just not the latest version of the book.

> http://jsninja.com/Functions#Function_Type
>
> // Do not use this function:
> | function isFunction( fn ) {
> | return !!fn && !fn.nodeName && fn.constructor != String &&
> | fn.constructor != RegExp && fn.constructor != Array &&
> | /function/i.test( fn + "" );
> | }
>
> Nobody should be using that code at this time. That isFunction relies on
> function decompilation. It fails across frames. It provides wrong
> results for some cases, the most obvious being any object whose toString
> contains substring "function" (any case).
>
> var book = {
> title : "functional javascript",
> valueOf : function(){ return this.title; }
> };
>
> That isFunction will result true.
>
> The justification for that function is based on the method overloading
> strategies used in the initial design of jQuery.
>
> We've been over and over this. I blogged about it with many examples, in
> 2007. That lousy function has gotten a lot of criticism. It seems hard

Yes I remember. Your blog is where I originally found out about function
decompilation (and its fragile nature) :)

> to believe that Resig could be unaware of that criticism.
>
> So why is he writing about it advocating its use? Making a one-time
> mistake is understandable. Advocating the use a well-known mistake
> defies explanation.

It's just an old text. I don't think he's advocating anything like this
any more.

--
kangax

0 new messages