john said:
as in the following?
JavaScript, JScript and the implementations in Opera and WebKit (and
some browsers i've never heard of) are all unique; different versions of
an implementation may vary widely; and the implementations from various
vendors are bound to vary. additionally there are some implementations
that run completely outside of a web browser.
Exactly; except that WebKit is not a browser (perhaps it is only poor
wording there), but a KHTML fork that consists of WebCore, the Mac OS-
influenced DOM implementation; JavaScriptCore (a KJS fork), the ECMAScript
language implementation; and probably other features.
You should quote properly, identifying all quotations as such (leading
pipes are customary on Usenet for third-party quotations), and providing a
citation, for example a Message-ID or the URI of a publicly accessible
resource. (See also said:
so what and when to test is a judgment call based on experience with
implementations (of the browsers you are interested in supporting) and
understanding of the relevant specifications?
Exactly, but browsers (clients) are still only one part of the equation.
are there more criteria i'm missing?
Some language features are known not to be available in older
implementations that can still be considered to be in use. You can either
avoid those language features (e.g., using hasOwnProperty() is avoided by
using iterator prototype methods), apply emulations if necessary (e.g.,
define Array.prototype.map() if it is unavailable), use emulating wrappers
instead (e.g., jsx.object._hasOwnProperty() to call
Object.prototype.hasOwnProperty() if available, using alternatives
otherwise), or use (eval-based) wrappers so that those language features
are hidden from the compiler and do not trigger a syntax error (e.g,
jsx.tryThis() to hide try-catch). In all of those cases it is only
necessary to test the language feature once, if that.
no doubt about that. i must not have been paying any attention when i
looked up the `className` property. where it's mentioned in the
JavaScript 1.3 reference it is clearly not what i was looking for.
| className: The fully qualified name of a Java class in a package
| other than `netscape`, `java`, or `sun` that is available to
| JavaScript.
Ahh, I did not know *that*. The Matrix has you!
is that "No" because they are "old enough" features provided by the
ECMAScript language and you have witnessed them working as expected?
i.e. based on the relevant specifications and experience with
implementations.
Yes. Date.prototype.getHours() is fully backwards-compatible, and I think
we can safely consider Netscape 2.0 and other runtime environments that
only support JavaScript 1.0 (which does not appear to implement
Number.prototype.toString()) to be extinct by now. It is not very
efficient (or not much fun, whatever term you prefer) to surf today's Web
with them anyway; BTDT (clicked away 43 script error *windows* on that
version's default homepage, redirected to <
http://netscape.aol.com/>).
The problem with this is that it is a often circulus virtuosus, pretty much
a self-fulfilling prophecy: Incompetent people deprecate browsers because
they cannot cope with deviations, often mistakenly think they are no longer
in use, they use not backwards-compatible features and as a result users
are forced to use newer browsers (or go to the more compatible competition)
because the Web (site) had become unusable with what they were used to.
is that "Yes" because it is a feature of the host environment and host
environments should be assumed hostile?
Not hostile; the languages would not be of much use without them. But they
should be assumed to vary, and little if anything should be taken for
granted.
now that i've spent some more time reading and testing i can see that
those test are indeed inadequate. particularly if you don't want to
throw script errors in very old browsers; which i gather could be
considered unacceptable or unimportant under certain conditions.
I do not think any of these tests would throw exceptions, though. Indeed,
if you added the `typeof' test, the script would become incompatible to
JavaScript 1.0 as that operator requires at least JavaScript 1.1. But as I
said, that should no longer be a concern today.
In fact, I think language features supported from JavaScript 1.3 (Netscape
4.06) on are safe to use without feature test by now (that is, provided it
is specified or supported by known implementations; this assessment is
likely to be subject to change as more implementations and versions are
tested). The next release of the ECMAScript Support Matrix will reflect
that, providing further hints as to what needs to be feature-tested
according to (my) current level of knowledge.
should i begin with the 5th edition keeping in mind that some of the new
language features will need feature testing or would it be better to
become familiar with the 3rd edition first?
Yes. And you should use the Shift key of your keyboard where appropriate.
Edition 5 claims to specify behavior common to current implementations, so
you should be aware of the changes from Edition 3 which is more widely
implemented at this point.
However, I must say that Edition 5 is even less readable for beginners than
Edition 3 (OK, neither was ever meant to be, but there is nothing
comparable): the abstraction level in the algorithms of the new Edition is
quite extreme, to say the least¹; it is hard even for me (who claims to
know Edition 3 and its implementations fairly well) to wrap my brain around
it (if they even bothered to set some inline links ...) And I am not even
mentioning the new Strict Mode deviations.
PointedEars
___________
¹ Example: Property read access (omitting the quotation prefixes here)
The production MemberExpression : MemberExpression [ Expression ] is
evaluated as follows:
1. Let baseReference be the result of evaluating MemberExpression.
2. Let baseValue be GetValue(baseReference).
3. Let propertyNameReference be the result of evaluating Expression.
4. Let propertyNameValue be GetValue(propertyNameReference).
5. Call CheckObjectCoercible(baseValue).
6. Let propertyNameString be ToString(propertyNameValue).
7. If the syntactic production that is being evaluated is contained in
strict mode code, let strict be true, else let strict be false.
8. Return a value of type Reference whose base value is baseValue and whose
referenced name is propertyNameString, and whose strict mode flag is
strict.
~~~~~~~
8.7.1 GetValue (V)
1. If Type(V) is not Reference, return V.
2. Let base be the result of calling GetBase(V).
3. If IsUnresolvableReference(V), throw a ReferenceError exception.
4. If IsPropertyReference(V), then
a. If HasPrimitiveBase(V) is false, then let get be the [[Get]] internal
method of base, otherwise let get be the special [[Get]] internal
method defined below.
b. Return the result of calling the get internal method using base as
its this value, and passing GetReferencedName(V) for the argument.
5. Else, base must be an environment record.
a. Return the result of calling the GetBindingValue (see 10.2.1)
concrete method of base passing GetReferencedName(V) and
IsStrictReference(V) as arguments.
~~~~~~~
8 Types
Within this specification, the notation “Type(x)†is used as shorthand for
“the type of x†where “type†refers to the ECMAScript language and
specification types defined in this clause.
~~~~~~~
8.7 The Reference Specification Type
[...]
• GetBase(V). Returns the base value component of the reference V.
[...]
• HasPrimitiveBase(V). Returns true if the base value is a Boolean, String,
or Number.
• IsPropertyReference(V). Returns true if either the base value is an
object or HasPrimitiveBase(V) is true; otherwise returns false.
• IsUnresolvableReference(V). Returns true if the base value is undefined
and false otherwise.
(Still there? We're just taking off ;-))
~~~~~~~
8.12.2 [[GetProperty]] (P)
When the [[GetProperty]] internal method of O is called with property name
P, the following steps are taken:
1. Let prop be the result of calling the [[GetOwnProperty]] internal
method of O with property name P.
2. If prop is not undefined, return prop.
3. Let proto be the value of the [[Prototype]] internal property of O.
4. If proto is null, return undefined.
5. Return the result of calling the [[GetProperty]] internal method of
proto with argument P.
8.12.3 [[Get]] (P)
When the [[Get]] internal method of O is called with property name P, the
following steps are taken:
8. Let desc be the result of calling the [[GetProperty]] internal method
of O with property name P.
9. If desc is undefined, return undefined.
10. If IsDataDescriptor(desc) is true, return desc.[[Value]].
11. Otherwise, IsAccessorDescriptor(desc) must be true so, let getter be
desc.[[Get]].
12. If getter is undefined, return undefined.
13. Return the result calling the [[Call]] internal method of getter
providing O as the this value and providing no arguments.
~~~~~~~
8.10.2 IsDataDescriptor ( Desc )
When the abstract operation IsDataDescriptor is called with property
descriptor Desc, the following steps are taken:
1. If Desc is undefined, then return false.
2. If both Desc.[[Value]] and Desc.[[Writable]] are absent, then return
false.
3. Return true.
~~~~~~~
8.6.1 Property Attributes
Attribute Name | Value Domain | Description
---------------+----------------+------------------------------------------
[[Value]] | Any ECMAScript | The value retrieved by reading
| language type | the property.
---------------+----------------+------------------------------------------
[[Writable]] | Boolean | If false, attempts by ECMAScript code
| | to change the property’s [[Value]]
| | attribute using [[Put]] will not succeed.
[...]
~~~~~~~
8.10.1 IsAccessorDescriptor ( Desc )
When the abstract operation IsAccessorDescriptor is called with property
descriptor Desc, the following steps are taken:
1. If Desc is undefined, then return false.
2. If both Desc.[[Get]] and Desc.[[Set]] are absent, then return false.
3. Return true.
~~~~~~~
13.2.1 [[Call]]
When the [[Call]] internal method for a Function object F is called with a
this value and a list of arguments, the following steps are taken:
1. Let funcCtx be the result of establishing a new execution context for
function code using the value of F's [[FormalParameters]] internal
property, the passed arguments List args, and the this value as
described in 10.4.3.
2. Let result be the result of evaluating the FunctionBody that is the
value of F's [
Code:
] internal property. If does not have a [[Code]]
internal property or if its value is an empty FunctionBody, then result
is (normal, undefined, empty).
3. Exit the execution context funcCtx, restoring the previous execution
context.
4. If result.type is throw then throw result.value.
5. If result.type is return then return result.value.
6. Otherwise result.type must be normal. Return undefined.
~~~~~~~
8.6.2 Object Internal Properties and Methods
[...]
Internal Property | Value Type | Description
---------------------+-----------------+-----------------------------------
[...]
[[FormalParameters]] | List of Strings | A possibly empty List containing
| | the identifier Strings of a
| | Function’s FormalParameterList.
| | Of the standard built-in
| | ECMAScript objects, only
| | Function objects implement
| | [[FormalParameterList]].
---------------------+-----------------+-----------------------------------
[[Code]] | ECMAScript code | The ECMAScript code of a function.
| | Of the standard built-in
| | ECMAScript objects, only
| | Function objects implement
| | [[Code]].
[...]
(etc. pp.)
~~~~~
(You did understand what was just said, didn't you? ;-))