Tải bản đầy đủ (.pdf) (18 trang)

Further Topics in JavaScript

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (189.95 KB, 18 trang )

Chapter 11. Further Topics in
had they been covered earlier. Now that you have read through the
and are experienced with the core JavaScript language, you are
he more advanced and detailed concepts presented here. You may
prefer, however, to move on to other chapters and learn about the specifics of client-side
JavaScript before returning to this chapter.
11.1 Data Type Conversion
We've seen that JavaScript is an untyped language (or, perhaps more accurately, a loosely
typed or dynamically typed language). This means, for example, that we don't have to
specify the data type of a variable when we declare it. Being untyped gives JavaScript the
flexibility and simplicity that are desirable for a scripting language (although those
features come at the expense of rigor, which is important for the longer, more complex
programs often written in stricter languages such as C and Java). An important feature of
JavaScript's flexible treatment of data types is the automatic type conversions it performs.
For example, if you pass a number to the
document.write( ) method, JavaScript
automatically converts that value into its equivalent string representation. Similarly, if
you test a string value in the condition of an if statement, JavaScript automatically
converts that string to a boolean value -- to false if the string is empty and to true
otherwise.
The basic rule is that when a value of one type is used in a context that requires a value of
some other type, JavaScript automatically attempts to convert the value as needed. So, for
example, if a number is used in a boolean context, it is converted to a boolean. If an
object is used in a string context, it is converted to a string. If a string is used in a numeric
context, JavaScript attempts to convert it to a number.
Table 11-1
JavaScript
This chapter covers miscellaneous JavaScript topics that would have bogged down
previous chapters
preceding chapters
tprepared to tackle


summarizes each of
these conversions -- it shows the conversion that is performed when a particular type of
value is used in a particular context. The sections that follow the table provide more
detail about type conversions in JavaScript.
Table 11-1. Automatic data type conversions
Value Context in which value is used
String Number Boolean Object
Undefined
value
"undefined" NaN false
Error
null "null" 0 false
Error
Table 11-1. Automatic data type conversions
Value Context in which value is used
String Number Boolean Object
Nonempty
string
As is
Numeric value of string or
NaN
true
String
object
Empty string As is
0 false
String
object
0 "0"
As is

false
Number
object
NaN "NaN"
As is
false
Number
object
Infinity
"Infinity"
As is
true
Number
object
Negative
infinity
"-Infinity"
As is
true
Number
object
Any other String value of
true
Number
number number
As is
object
true "true" 1
As is
Boolean

object
false "false" 0
As is
object
Boolean
Object
toString( )
valueOf( ) or toString(
) or NaN
true
As is
11.1.1 Object-to-Primitive Conversion
Table 11-1 specifies how JavaScript objects are converted to primitive values. Several
additional discussion, however. First, note that
whenever a non-null context, it converts to true. This is true
for all objects (including all arrays and functions), even wrapper objects that represent
the following objects convert
to true when used in a boolean context:
details of this conversion require
object is used in a boolean
primitive values that convert to false. For example, all of
[1]
[1]
Note, though, that in JavaScript 1.1 and 1.2 these objects all convert to false, which is ECMAScript compliant.
new Boolean(false) // Internal value is false, but object converts to
true
new Number(0)
new String("")
new Array( )
Table 11-1 shows that objects are converted to num

method of the object. Most objects inherit the defau
bers by first calling the valueOf( )
lt valueOf( ) method of Object,
which simply returns the object itself. Since the default valueOf( ) method does not
return a primitive value, JavaScript next tries to convert the object to a number by calling
its toString( ) method and converting the resulting string to a number.
s
empty string, which (as you can see in the table) converts to the number zero! Also, if an
array has a single element that is a number n, the array converts to a string representation
t,
NaN.
[2]
This leads to interesting results for arrays. Recall that the toString( ) method of array
converts the array elements to strings, then returns the result of concatenating these
strings, with commas in between. Therefore, an array with no elements converts to the
of n, which is then converted back to n itself. If an array contains more than one elemen
or if its one element is not a number, the array converts to
[2]
Note, however, that in JavaScript 1.1 and 1.2, when an array is used in a numeric context it is converted to its length.
Table 11-1 specifies how an object is converted when used in a string context and how it
is converted when used in a numeric context. However, there are a couple of places in
JavaScript where the context is ambiguous! The + operator and the comparison operators
(<, <=, >, and >=) operate on both numbers and strings, so when an object is used with
one of these operators, it is not clear whether it should be converted to a number or a
string. In most cases, JavaScript first attempts to convert the object by calling its
e
case, JavaScript then tries to convert the object to a string by calling its toString( )
d with the +
toString( )
because Date has both toString( ) and valueOf( ) methods. When a Date is used with

+, you almost always want to perform a string concatenation. But when using a Date with
the comparison operators, you almost always want to perform a numeric comparison to
determine which of two times is earlier than the other.
Most objects either don't have
valueOf( ) methods or don't have valueOf( ) methods
that return useful results. When you use an object with the + operator, you usually get
valueOf( ) method. If this method returns a primitive value (usually a number), that
value is used. Often, however, valueOf( ) simply returns the unconv rted object; in this
method.
There is only one exception to this conversion rule: when a Date object is use
perator, conversion is performed with the method. This exception exists o
string concatenation rather than addition. When you use an object with a comparison
operator, you usually get string comparison rather than numeric comparison.
An object that defines a custom valueOf( ) method may behave differently. If you
define a valueOf( ) method that returns a number, you can use arithmetic and other
operators with your object, but adding your object to a string may not behave as you
expect: the toString( ) method is no longer called, and a string representation of the
number returned by valueOf( ) is concatenated to the string.
Finally, remember that valueOf( ) is not called toNumber( ): strictly speaking, its job
is to convert an object to a reasonable primitive value, so some objects may have
valueOf( ) t return strings. methods tha
11.1.2 Explicit Type Conversions
Table 11-1 listed the automatic data type conv
possible to explicitly convert values from one
ersions that JavaScript performs. It is also
type to another. JavaScript does not define
a cast operator as C, C++, and Java do, but it does provide similar facilities for converting
g(
e type. For example, you could convert any value x to a string with String(x)
ject(y).

here are a few other tricks that can be useful for performing explicit conversions. To
convert a value to a string, concatenate it with the empty string:
var x_as_string = x + "";
To force a value to a number, subtract zero from it:
var x_as_number = x - 0;
And to force a value to boolean, use the ! operator twice:
rt data to whatever type is
required, explicit conversions are usually unnecessary hey are occasionally helpful,
and more precise.
11.1.3 Converting Numbers to Strings
ed in JavaScript.
Although it usually happens automatically, there are a couple of useful ways to explicitly
data values.
As of JavaScript 1.1 (and the ECMA-262 standard),
Number( ) , Boolean( ), Strin
), and Object( ) may be called as functions as well as being invoked as constructors.
When invoked in this way, these functions attempt to convert their arguments to the
appropriat
and convert any value y to an object with Ob
T
var x_as_boolean = !!x;
Because of JavaScript's tendency to automatically conve
. T
however, and can also be used to make your code clearer
The number-to-string conversion is probably the one most often perform
perform this conversion. We saw two of them above:
var string_value = String(number); // Use the String( ) constructor
var string_value = number + ""; // Concatenate with the empty string
Another technique for converting numbers to strings is with the toString( ) method:
The toString( ) method of the Number object (primitive numbers are converted to

nal argument that
fy the argument, the
conversion is done in base 10. But you can also convert numbers in other bases (between
2 and 36).
[3]
as a function
string_value = number.toString( );
Number objects so that this method can be called) takes an optio
specifies a radix, or base, for the conversion. If you do not speci
For example:
[3]
Note that the ECMAScript specification supports the radix argument to the toString( ) method, but it allows the method to return
an implementation-defined string for any radix other than 10. Thus, conforming implementations may simply ignore the argument and always
return a base-10 result. In practice, implementations from Netscape and Microsoft do honor the requested radix.
var n = 17;
binary_string = n.toString(2); // Evaluates to "10001"
octal_string = "0" + n.toString(8); // Evaluates to "021"
hex_string = "0x" + n.toString(16); // Evaluates to "0x11"
A shortcoming of JavaScript prior to JavaScript 1.5 is that there is no built-in way to
convert a number to a string and specify the number of decimal places to be included, or
to specify whether exponential notation should be used. This can make it difficult to
display numbers that have traditional formats, such as numbers that represent monetary
values.
ECMAScript v3 and JavaScript 1.5 solve this problem by adding three new number-to-
string methods to the Number class. toFixed( ) converts a number to a string and
displays a specified number of digits after the decimal point. It does not use exponential
notation. toExponential( ) converts a number to a string using exponential notation,
with one digit before the decimal point and a specified number of digits after the decimal
point.
toPrecision( ) displays a number using the specified number of significant

digits. It uses exponential notation if the number of significant digits is not large enough
to display the entire integer portion of the number. Note that all three of these methods
round the trailing digits of the resulting string as appropriate. Consider the following
examples:
var n = 123456.789;
n.toFixed(0); // "123457"
n.toFixed(2); // "123456.79"
n.toExponential(1); // "1.2e+5"
n.toExponential(3); // "1.235e+5"
n.toPrecision(4); // "1.235e+5"
n.toPrecision(7); // "123456.8"
var number = string_value - 0;
The trouble with this g-to-number conversion is strict. It
works only with base- s, and although it does allow leading and trailing spaces,
it does not s t
To allow m s, you can .
These func rn any num of a string, ignoring any
trailing no s o s
both intege
parseInt(
11.1.4 Converting Strings to Numbers
We've seen that strings that represent numbers are automatically converted to actual
numbers when used in a numeric context. As shown earlier, we can make this conversion
explicit:
var number = Number(string_value);
sort of strin
10 number
that it is overly
allow any non-space character
ore flexible conversion

tions convert and retu
o appear in the string following the number.
use parseInt( ) and parseFloat( )
ber at the beginning
n-numbers. parseInt( ) parse
rs and floating-point numbers. If
) interprets it as a hexadecimal
nly integers, while parseFloat( ) parse
a string begins with "0x" or "0X",
number.
[4]
For example:
(but not "0x" or "0X"), parseInt( ) may parse it as an octal
[4]
The ECMASc ays that if a string begins with "0"
number or as a de unspecified, y
leading zeros, un
parseInt( Ret
parseFloa 4 meters"); // Ret
arseInt("12.34"); // Returns 12
arseInt("0xFF"); // Returns 255
parseInt( ) can even take a second argument specifying the radix (base) of the number
to be parsed. Legal values are between 2 and 36. For example:
parseInt("11", 2); // Returns 3 (1*2 + 1)
parseInt("ff", 16); // Returns 255 (15*16 + 15)
parseInt("zz", 36); // Returns 1295 (35*36 + 35)
parseInt("077", 8); // Returns 63 (7*8 + 7)
parseInt("077", 10); // Returns 77 (7*10 + 7)
If parseInt( ) or parseFloat( ) cannot convert the specified string to a number, it
returns NaN:

parseInt("eleven"); // Returns NaN
parseFloat("$72.47"); // Returns NaN
ript specification s
cimal number. Because the behavior is
less you explicitly specify the radix to be used!
"3 blind mice"); //
t("3.1
ou should never use parseInt( ) to parse numbers with
urns 3
urns 3.14
p
p
11.2 By Value Versus by Reference
ou
ons are performed in
that language.
e data values. These techniques
is the
e and
d the
is
the datum is passed to the function; if the
um, the two distinct pieces of data must represent exactly the same value (which
only
y of the value; references to that value are manipulated.
In JavaScript, as in all programming languages, there are three important ways that y
can manipulate a data value. First, you can copy it; for example, by assigning it to a new
variable. Second, you can pass it as an argument to a function or method. Third, you can
compare it with another value to see if the two values are equal. To understand any
programming language, you must understand how these three operati

There are two fundamentally distinct ways to manipulat
are called "by value" and "by reference." When a value is manipulated by value, it
lue of the datum that matters. In an assignment, a copy of the actual value is madva
that copy is stored in a variable, object property, or array element; the copy an
original are two totally independent valu
ssed by value to a function, a copy of
es that are stored separately. When a datum
pa
function modifies the value, the change affects only the function's copy of the datum -- it
does not affect the original datum. Finally, when a datum is compared by value to another
dat
usually means that a byte-by-byte comparison finds them to be equal).
The other way of manipulating a value is by reference. With this technique, there is
one actual cop
[5]
If a value is
references to it. It is these references that are copied, passed, and compared. So, in an
assignment made by reference, it is the reference to the value that is assigned, not a copy
s to the
to. Both references are equally valid and both
ca the value -- if the value is changed through one reference, that
e situation is similar when a value
are visible outside the function. Finally, when a value is compared to another by
[5]
C programmers and anyone else familiar with the concept of pointers should understand the idea of a reference in this context. Note,
however, that JavaScript does not support pointers.
manipulated by reference, variables do not hold that value directly; they hold only
of the value and not the value itself. After the assignment, the new variable refer
same value that the original variable refers
n be used to manipulate

change also appears through the original reference. Th
is passed to a function by reference. A reference to the value is passed to the function,
and the function can use that reference to modify the value itself; any such modifications
reference, the two references are compared to see if they refer to the same unique copy of
a value; references to two distinct values that happen to be equivalent (i.e., consist of the
same bytes) are not treated as equal.
These are two very different ways of manipulating values, and they have important
implications that you should understand.
Table 11-2 summarizes these implications. This
discussion of manipulating data by value and by reference has been a general one, but the
distinctions apply to all programming languages. The sections that follow explain how
these distinctions app
ly specifically to JavaScript; they discuss which data types are
manipulated by value and which are manipulated by reference.

Tài liệu bạn tìm kiếm đã sẵn sàng tải về

Tải bản đầy đủ ngay
×