ECMA-262把
内置对象(built-in object)定义为“由ECMAScript实现提供的、独立于宿主环境的所有对象,在ECMAScript程序开始执行时出现”。这意味着开发者不必明确实例化内置对象,它已被实例化了。ECMA-262只定义了两个内置对象,即
Global和
Math(它们也是本地对象,根据定义,每个内置对象都是本地对象)。
1.
Global对象
Global对象是ECMAScript中最特别的对象,因为实际上它根本不存在。如果尝试编写下面的代码,将得到错误:

错误消息显示
Global不是对象,但刚才不是说Global是对象吗?没错。这里需要理解的主要概念是,在ECMAScript中,不存在独立的函数,所有函数都必须是某个对象的方法。本书前面介绍的函数,如
isNaN()、
isFinite()、
parseInt()和
parseFloat()等,看起来都像独立的函数。实际上,它们都是
Global对象的方法。而且
Global对象的方法不止这些。
encodeURI()和
encodeURIComponent()方法用于编码传递给浏览器的URI(统一资源标识符)。有效的URI不能包含某些字符,如空格。这两个方法用于编码URI,这样用专门的UTF-8编码替换所有的非有效字符,就可以使浏览器仍能够接受并理解它们。
encodeURI()方法用于处理完整的URI(例如,
http://www.wrox.com/illegal value.htm),而
encodeURIComponent()用于处理URI的一个片断(如前面的URI中的
illegal value.htm)。这两个方法的主要区别是
encodeURI()方法不对URI中的特殊字符进行编码,如冒号、前斜杠、问号和英镑符号,而
encodeURIComponent()则对它发现的所有非标准字符进行编码。例如:


这段代码输出两个值:

可以看到,除空格外,第一个URI无任何改变,空格被替换为
%20。第二个URI中的所有非字母数字字符都被替换成它们对应的编码,基本上使这个URI变得无用。这就是
encodeURI()可以处理完整URI,而
encodeURIComponent()只能处理附加在已有URI末尾的字符串的原因。
自然,还有两个方法用于解码编码过的URI,即
decodeURI()和
decodeURIComponent()。如你所料,这两个方法所做的恰与其对应的方法相反。
decodeURI()方法只对用
encodeURI()方法替换的字符解码。例如,
%
20将被替换为空格,而
%
23不会被替换,因为它表示的是英镑符号(
#),
encodeURI()并不替换这个符号。同样的,
decodeURIComponent()会解码所有
encodeURIComponent()
编码过的字符,意味着它将对所有的特殊值解码。例如:

这段代码输出两个值:

在这个例子中,变量
uri存放的是用
encodeURIComponent()编码的字符串。生成的值说明了应用两个解码方法时会发生的事情。第一个值由
decodeURI()输出,把
%20替换成空格。第二个值由
decodeURIComponent()输出,替换所有的特殊。
这些URI方法
encodeURI()、encodeURIComponent()、decodeURI()和decodeURICom- ponent()代替了BOM的escape()和unescape()方法。URI方法更可取,因为它们会对所有Unicode符号编码,而BOM方法只能对ASCII符号正确编码。尽量避免使用escape()和unescape()方法。
最后一个方法可能是整个ECMAScript语言中最强大的方法,即
eval()方法。该方法就像整个ECMAScript的解释程序,接受一个参数,即要执行的ECMAScript(或JavaScript)字符串。例如:

这行代码的功能等价于下面的代码:


当解释程序发现
eval()调用时,它将把参数解释为真正的ECMAScript语句,然后把它插入该函数所在的位置。这意味着
eval()调用内部引用的变量可在参数以外定义:

这里,变量
msg是在
eval()调用的环境外定义的,而警告仍然显示的是文本
"hello world",因为第二行代码将被替换为一行真正的代码。同样,可以在
eval()调用内部定义函数或变量,然后在函数外的代码中引用:

这里,函数
sayHi()是在
eval()调用内部定义的。因为该调用将被替换为真正的函数,所以仍可在接下来的一行中调用
sayHi()。
这种功能非常强大,不过也非常危险。使用
eval()时要极度小心,尤其在给它传递用户输入的数据时。恶意的用户可能会插入对站点或应用程序的安全性有危害的值(叫做代码注入)。
Global对象不只有方法,它还有属性。还记得那些特殊值
undefined、
NaN和
Infinity吗?它们都是
Global对象的属性。此外,所有本地对象的构造函数也都是
Global对象的属性。下表较详细地说明了
Global对象的所有属性:
属
性
|
说
明
|
undefined
|
Undefined
类型的字面量
|
NaN
|
非数
的专用数值
|
Infinity
|
无穷大值的专用数值
|
Object
|
Object
的构造函数
|
Array
|
Array
的构造函数
|
Function
|
Function
的构造函数
|
Boolean
|
Boolean
的构造函数
|
String
|
String
的构造函数
|
Number
|
Number
的构造函数
|
Date
|
Date
的构造函数
|
![]() |
RegExp
的构造函数
|
Error
|
Error
的构造函数
|
EvalError
|
EvalError
的构造函数
|
RangeError
|
RangeError
的构造函数
|
ReferenceError
|
ReferenceError
的构造函数
|
SyntaxError
|
SyntaxError
的构造函数
|
TypeError
|
TypeError
的构造函数
|
URIError
|
URIError
的构造函数
|
2.
Math对象
Math对象是在高中数学课就学过的内置对象。它知道解决最复杂的数学问题的所有公式,如果给它要处理的数字,即能计算出结果。
Math对象有几个属性,主要是数学界的专用值。下表类出了这些属性:
属
性
|
说
明
|
E
|
值
e
,自然对数的底
|
LN10
|
10
的自然对数
|
LN2
|
2
的自然对数
|
LOG2E
|
以
2
为底
E
的对数
|
LOG10E
|
以
10
为底
E
的对数
|
PI
|
值π
|
SQRT1_2
|
1/2
的平方根
|
SQRT2
|
2
的平方根
|
虽然这些值的意义与用法不在本书讨论范围内,但如果清楚它们是什么,在需要时,即可使用它们。
Math对象还包括许多专门用于执行简单的及复杂的数学计算的方法。
方法
min()
和
max()
用于判断一组数中的最大值和最小值。这两个方法都可接受任意多个参数:



对于数字3、54、32和16,
max()返回54,
min()返回3。用这些方法,可免去用循环或
if语句来判断一组数中的最大值。
另一个方法
abs()
返回数字的绝对值。绝对值是负数的正值版本(正数的绝对值就是它自身)。

这个例子中,
abs(-1)返回
1,
abs(1)也返回
1。
下一组方法用于把小数舍入成整数。处理舍入操作的方法有三个,即
ceil()、
floor()和
round(),它们的处理方法不同:
q 方法
ceil()表示向上舍入函数,总是把数字向上舍入到最接近的值。
q 方法
floor()表示向下舍入函数,总是把数字向下舍入到最接近的值。
q 方法
round()表示标准的舍入函数,如果数字与下一个整数的差不超过0.5,则向上舍入,否则向下舍入。这是在初中学过的舍入规则。
为说明每种方法的处理方式,考虑使用值
25.5:

对于
ceil()和
round(),传递
25.5,返回的是
26,而
floor()返回的是25。注意不要交替使用这些方法,因为最后可能得到与预期不符的结果。
另一组方法与指数的用法有关。这些方法包括
exp(),用于把
Math.E升到指定的幂;
log()用于返回特定数字的自然对数;
pow()用于把指定的数字升到指定的幂;
sqrt()用于返回指定数字的平方根。
方法
exp()和
log()本质上功能相反,
exp()把
Math.E升到特定的幂,
log()则判断
Math.E的多少次指数才等于指定的值。例如:


这里,首先用
exp()把
Math.E升到10次幂,然后
log()返回10,即等于数字
iNum必需的指数。很多人都对此感到迷茫。全世界的高中生和数学系的大学生都被此类问题难倒过。如果你对自然对数一无所知,那么有可能永远都不需要为它编写代码。
方法
pow()用于把数字升到指定的幂,如把2升到10次幂(在数学中表示为2
10):

pow()的第一个参数是基数,此例子中是2。第二个参数是要升到的幂,此例子中是10。
不建议把
Math.E作为pow()方法的基数。最好使用exp()对Math.E进行升幂运算,因为它是专用运算,计算出的值更精确。
这组方法中的最后一个方法是
sqrt(),用于返回指定数字的平方根。它只有一个参数,即要求平方根的数字。要求4的平方根,只需要用一行代码:

当然,4的平方根是2,就是这行代码的输出。
你也许会问“为什么平方根必须利用指数”?实际上,数字平方根就是它的1/2
次幂。例如,21/2
就是2
的平方根。
Math对象还有一整套三角函数方法。下表列出了这些方法:
方
法
|
说
明
|
acos(x)
|
返回
x
的反余弦值
|
asin(x)
|
返回
x
的反正弦值
|
atan(x)
|
返回
x
的反正切值
|
atan2(y,x)
|
返回
y/x
的反余弦值
|
cos(x)
|
返回
x
的余弦值
|
sin(x)
|
返回
x
的正弦值
|
![]() |
返回
x
的正切值
|
即使这些方法是ECMA-262
定义的,结果也是由实现决定的,因为每个值的计算方法都有很多,从而使得不同的实现生成的结果的精度也不同。
Math对象的最后一个方法是
random(),该方法返回一个0到1之间的随机数,不包括0和1。这是在主页上显示随机引述或新闻的站点常用的工具。可用下面的形式调用
random()方法,在某个范围内选择随机数:

这里使用方法
floor(),因为
random()返回的都是小数值,也就是说,用它乘以一个数,然后再加上一个数,得到的仍然是小数值。通常你想选择一个随机整数值。因此,必须使用
floor()方法。如果想选择一个1到10之间的数,代码如下:

可能出现的值有10个(1到10),这些值中的第一个是1。如果想选择2到10之间的值,代码如下:

从2到10,只有9个数字,所以选项总数为9,其中第一个值是2。许多时候,使用计算选项总数的函数和第一个可用的值更容易些:

使用函数,可很容易地选择
Array中的随机项:

这里,
selectFrom()函数的第二个参数是数组的长度减1,即数组中最后一个元素的位置。