首页 > 代码库 > 第五章 单体内置对象

第五章 单体内置对象

ECMA-262 对内置对象的定义是:“由ECMAScript 实现提供的、不依赖于宿主环境的对象,这些对象在ECMAScript 程序执行之前就已经存在了。”意思就是说,开发人员不必显式地实例化内置对象,因为它们已经实例化了。

我们已经介绍了大多数内置对象,例如Object、Array 和String。ECMA-262 还定义了两个单体内置对象:Global 和Math。

7.1 Global对象

Global(全局)对象可以说是ECMAScript 中最特别的一个对象了,因为不管你从什么角度上看,这个对象都是不存在的。ECMAScript 中的Global 对象在某种意义上是作为一个终极的“兜底儿对象”来定义的。换句话说,不属于任何其他对象的属性和方法,最终都是它的属性和方法。事实上,没有全局变量或全局函数;所有在全局作用域中定义的属性和函数,都是Global 对象的属性。本书前面介绍过的那些函数,诸如isNaN()、isFinite()、parseInt()以及parseFloat(),实际上全都是Global对象的方法。除此之外,Global 对象还包含其他一些方法。

1、URI编码方法

Global 对象的encodeURI()和encodeURIComponent()方法可以对URI(Uniform ResourceIdentifiers,通用资源标识符)进行编码,以便发送给浏览器。有效的URI 中不能包含某些字符,例如空格。而这两个URI 编码方法就可以对URI 进行编码,它们用特殊的UTF-8 编码替换所有无效的字符,从而让浏览器能够接受和理解。

其中,encodeURI()主要用于整个URI(例如,http://www.wrox.com/illegal value.htm),而encodeURIComponent()主要用于对URI 中的某一段(例如前面URI 中的illegal value.htm)进行编码。
它们的主要区别在于,encodeURI()不会对本身属于URI 的特殊字符进行编码,例如冒号、正斜杠、问号和井字号;而encodeURIComponent()则会对它发现的任何非标准字符进行编码。来看下面的例子。

var uri = "http://www.wrox.com/illegal value.htm#start";
//"http://www.wrox.com/illegal%20value.htm#start"
alert(encodeURI(uri));
//"http%3A%2F%2Fwww.wrox.com%2Fillegal%20value.htm%23start"
alert(encodeURIComponent(uri));

与encodeURI()和encodeURIComponent()方法对应的两个方法分别是decodeURI()和decodeURIComponent()。其中,decodeURI()只能对使用encodeURI()替换的字符进行解码。同样地,decodeURIComponent()能够解码使用encodeURIComponent()编码的所有字符,即它可以解码任何特殊字符的编码。来看下面的例子:

var uri = "http%3A%2F%2Fwww.wrox.com%2Fillegal%20value.htm%23start";
//http%3A%2F%2Fwww.wrox.com%2Fillegal value.htm%23start
alert(decodeURI(uri));
//http://www.wrox.com/illegal value.htm#start
alert(decodeURIComponent(uri));

2、eval()方法

eval()方法就像是一个完整的ECMAScript 解析器,它只接受一个参数,即要执行的ECMAScript (或JavaScript)字符串。看下面的例子:
eval("alert(‘hi‘)");
这行代码的作用等价于下面这行代码:
alert("hi");
当解析器发现代码中调用eval()方法时,它会将传入的参数当作实际的ECMAScript 语句来解析,然后把执行结果插入到原位置。通过eval()执行的代码被认为是包含该次调用的执行环境的一部分,因此被执行的代码具有与该执行环境相同的作用域链。这意味着通过eval()执行的代码可以引用在包含环境中定义的变量,举个例子:

var msg = "hello world";
eval("alert(msg)"); //"hello world"

可见,变量msg 是在eval()调用的环境之外定义的,但其中调用的alert()仍然能够显示"hello world"。这是因为上面第二行代码最终被替换成了一行真正的代码。同样地,我们也可以在eval()调用中定义一个函数,然后再在该调用的外部代码中引用这个函数:

eval("function sayHi() { alert(‘hi‘); }");
sayHi();

显然,函数sayHi()是在eval()内部定义的。但由于对eval()的调用最终会被替换成定义函数的实际代码,因此可以在下一行调用sayHi()。对于变量也一样:

eval("var msg = ‘hello world‘; ");
alert(msg); //"hello world"

在eval()中创建的任何变量或函数都不会被提升,因为在解析代码的时候,它们被包含在一个字符串中;它们只在eval()执行的时候创建。
严格模式下,在外部访问不到eval()中创建的任何变量或函数,因此前面两个例子都会导致错误。
同样,在严格模式下,为eval 赋值也会导致错误:

"use strict";
eval = "hi"; //causes error

3、Global 对象的属性

特殊的值undefined、NaN 以及Infinity 都是Global 对象的属性。此外,所有原生引用类型的构造函数,像Object 和Function,也都是Global 对象的属性。下表列出了Global 对象的所有属性。

属 性 说 明 属 性 说 明
undefined 特殊值undefined  Date  构造函数Date
NaN 特殊值NaN  RegExp  构造函数RegExp
Infinity 特殊值Infinity Error   构造函数Error
Object 构造函数Object EvalError   构造函数EvalError
Array 构造函数Array RangeError   构造函数RangeError
Function 构造函数Function EeferenceError   构造函数ReferenceError
Boolean 构造函数Boolean SyntaxError   构造函数SyntaxError
String 构造函数String TypeError   构造函数TypeError
Number 构造函数Number URIError   构造函数URIError

 

 

 

 

 

 

 

 

ECMAScript 5 明确禁止给undefined、NaN 和Infinity 赋值,这样做即使在非严格模式下也会导致错误。

4、window对象

ECMAScript 虽然没有指出如何直接访问Global 对象,但Web 浏览器都是将这个全局对象作为window 对象的一部分加以实现的。因此,在全局作用域中声明的所有变量和函数,就都成为了window对象的属性。来看下面的例子。

var color = "red";
function sayColor(){
alert(window.color);
}
window.sayColor(); //"red"

另一种取得Global 对象的方法是使用以下代码:

var global = function(){
return this;
}();

以上代码创建了一个立即调用的函数表达式,返回this 的值。如前所述,在没有给函数明确指定this 值的情况下(无论是通过将函数添加为对象的方法,还是通过调用call()或apply()),this值等于Global 对象。而像这样通过简单地返回this 来取得Global 对象,在任何执行环境下都是可行的。

7.2 Math对象

ECMAScript 还为保存数学公式和信息提供了一个公共位置,即Math 对象。与我们在JavaScript 直接编写的计算功能相比,Math 对象提供的计算功能执行起来要快得多。Math 对象中还提供了辅助完成这些计算的属性和方法。

1、Math对象的属性

Math 对象包含的属性大都是数学计算中可能会用到的一些特殊值。

属 性 说 明
Math.E 自然对数的底数,即常量e的值
Math.LN10 10的自然对数
Math.LN2 2的自然对数
Math.LOG2E 以2为底e的对数
Math.LOG10E 以10为底e的对数
Math.PI π 的值
Math.SQRT1_2 1/2的平方根(即2的平方根的倒数)
Math.SQRT2 2的平方根

 

 

 

 

 

 

 

 

2、min() 和 max() 对象的属性

min()和max()方法用于确定一组数值中的最小值和最大值。这两个方法都可以接收任意多个数值参数.

var max = Math.max(3, 54, 32, 16);
alert(max); //54
var min = Math.min(3, 54, 32, 16);
alert(min); //3

要找到数组中的最大或最小值,可以像下面这样使用apply()方法。

var values = [1, 2, 3, 4, 5, 6, 7, 8];
var max = Math.max.apply(Math, values);

这个技巧的关键是把Math 对象作为apply()的第一个参数,从而正确地设置this 值。然后,可以将任何数组作为第二个参数。

3、舍入方法

下面来介绍将小数值舍入为整数的几个方法:Math.ceil()、Math.floor()和Math.round()。
这三个方法分别遵循下列舍入规则:
? Math.ceil()执行向上舍入,即它总是将数值向上舍入为最接近的整数;
? Math.floor()执行向下舍入,即它总是将数值向下舍入为最接近的整数;
? Math.round()执行标准舍入,即它总是将数值四舍五入为最接近的整数。
下面是使用这些方法的示例:

alert(Math.ceil(25.9)); //26
alert(Math.ceil(25.5)); //26
alert(Math.ceil(25.1)); //26
alert(Math.round(25.9)); //26
alert(Math.round(25.5)); //26
alert(Math.round(25.1)); //25
alert(Math.floor(25.9)); //25
alert(Math.floor(25.5)); //25
alert(Math.floor(25.1)); //25

 

4、random() 方法

Math.random()方法返回大于等于0 小于1 的一个随机数。对于某些站点来说,这个方法非常实用,因为可以利用它来随机显示一些名人名言和新闻事件。套用下面的公式,就可以利用Math.random()从某个整数范围内随机选择一个值。

值 = Math.floor(Math.random() * 可能值的总数 + 第一个可能的值)

公式中用到了Math.floor()方法,这是因为Math.random()总返回一个小数值。而用这个小数值乘以一个整数,然后再加上一个整数,最终结果仍然还是一个小数。

举例来说,如果你想选择一个1到10 之间的数值,可以像下面这样编写代码:

var num = Math.floor(Math.random() * 10 + 1);

总共有10 个可能的值(1 到10),而第一个可能的值是1。

而如果想要选择一个介于2 到10 之间的值,就应该将上面的代码改成这样:

var num = Math.floor(Math.random() * 9 + 2);

从2 数到10 要数9 个数,因此可能值的总数就是9,而第一个可能的值就是2。

多数情况下,其实都可以通过一个函数来计算可能值的总数和第一个可能的值,例如:

function selectFrom(lowerValue, upperValue) {
  var choices = upperValue - lowerValue + 1;
  return Math.floor(Math.random() * choices + lowerValue);
}
var num = selectFrom(2, 10);
alert(num); // 介于 2 和10 之间(包括 2 和 10)的一个数值

函数selectFrom()接受两个参数:应该返回的最小值和最大值。而用最大值减最小值再加1 得到了可能值的总数,然后它又把这些数值套用到了前面的公式中。这样,通过调用selectFrom(2,10)就可以得到一个介于2 和10 之间(包括2 和10)的数值了。

利用这个函数,可以方便地从数组中随机取出一项,例如:

var colors = ["red", "green", "blue", "yellow", "black", "purple", "brown"];
var color = colors[selectFrom(0, colors.length-1)];
alert(color); // 可能是数组中包含的任何一个字符串

 

5、其他方法

Math 对象中还包含其他一些与完成各种简单或复杂计算有关的方法,但详细讨论其中每一个方法的细节及适用情形超出了本书的范围。下面我们就给出一个表格,其中列出了这些没有介绍到的Math对象的方法。

方 法 说 明 方 法 说 明
Math.abs(num) 返回num 的绝对值 Math.asin(x)  返回x 的反正弦值
Math.exp(num) 返回Math.E 的num 次幂 Math.atan(x)  返回x 的反正切值
Math.log(num) 返回num 的自然对数 Math.atan2(y,x)  返回y/x 的反正切值
Math.pow(num,power) 返回num 的power 次幂 Math.cos(x)   返回x 的余弦值
Math.sqrt(num) 返回num 的平方根 Math.sin(x)  返回x 的正弦值
Math.acos(x) 返回x 的反余弦值 Math.tan(x)  返回x 的正切值

 

第五章 单体内置对象