Global对象
Global(全局)对象能够说是ECMAScript 中最特别的一个对象了,由于无论你从什么角度上看,这个对象都是不存在的。ECMAScript 中的Global 对象在某种意义上是做为一个终极的“兜底儿对象”来定义的。换句话说,不属于任何其余对象的属性和方法,最终都是它的属性和方法。事实上,没有全局变量或全局函数;全部在全局做用域中定义的属性和函数,都是Global 对象的属性。本书前面介绍过的那些函数,诸如isNaN()、isFinite()、parseInt()以及parseFloat(),实际上全都是Global 对象的方法。除此以外,Global 对象还包含其余一些方法。算法
1. URI 编码方法
Global 对象的encodeURI()和encodeURIComponent()方法能够对URI(Uniform Resource Identifiers,通用资源标识符)进行编码,以便发送给浏览器。有效的URI 中不能包含某些字符,例如空格。而这两个URI 编码方法就能够对URI 进行编码,它们用特殊的UTF-8 编码替换全部无效的字符,从而让浏览器可以接受和理解。
其中,encodeURI()主要用于整个URI(例如,http://www.wrox.com/illegal value.htm),而encode-URIComponent()主要用于对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()编码后的结果是除了空格以外的其余字符都原封不动,只有空格被替换成了%20。而encodeURIComponent()方法则会使用对应的编码替换全部非字母数字字符。这也正是能够对整个URI 使用encodeURI(),而只能对附加在现有URI 后面的字符串使用encodeURIComponent() 的缘由所在。安全
注:通常来讲, 咱们使用encodeURIComponent() 方法的时候要比使用encodeURI()更多,由于在实践中更常见的是对查询字符串参数而不是对基础URI进行编码。app
与encodeURI()和encodeURIComponent()方法对应的两个方法分别是decodeURI()和decodeURIComponent()。其中,decodeURI()只能对使用encodeURI()替换的字符进行解码。例如,它可将%20 替换成一个空格,但不会对%23 做任何处理,由于%23 表示井字号(#),而井字号不是使用encodeURI()替换的。一样地,decodeURIComponent()可以解码使用encodeURIComponent()编码的全部字符,即它能够解码任何特殊字符的编码。来看下面的例子:dom
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));函数
这里,变量uri 包含着一个由encodeURIComponent()编码的字符串。在第一次调用decodeURI()输出的结果中,只有%20 被替换成了空格。而在第二次调用decodeURIComponent()输出的结果中,全部特殊字符的编码都被替换成了原来的字符,获得了一个未经转义的字符串(但这个字符串并非一个有效的URI)。this
2. eval()方法
如今,咱们介绍最后一个——大概也是整个ECMAScript 语言中最强大的一个方法: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 errorcode
注:可以解释代码字符串的能力很是强大,但也很是危险。所以在使用eval()时必须极为谨慎,特别是在用它执行用户输入数据的状况下。不然,可能会有恶意用户输入威胁你的站点或应用程序安全的代码(即所谓的代码注入)。
3. Global 对象的属性
Global 对象还包含一些属性,其中一部分属性已经在本书前面介绍过了。例如,特殊的值undefined、NaN 以及Infinity 都是Global 对象的属性。此外,全部原生引用类型的构造函数,像Object 和Function,也都是Global 对象的属性。下表列出了Global 对象的全部属性。
ECMAScript 5 明确禁止给undefined、NaN 和Infinity 赋值,这样作即便在非严格模式下也会致使错误。
4. window 对象
ECMAScript 虽然没有指出如何直接访问Global 对象,但Web 浏览器都是将这个全局对象做为window 对象的一部分加以实现的。所以,在全局做用域中声明的全部变量和函数,就都成为了window对象的属性。来看下面的例子。
var color = "red";
function sayColor(){
alert(window.color);
}
window.sayColor(); //"red"
这里定义了一个名为color 的全局变量和一个名为sayColor()的全局函数。在sayColor()内部,咱们经过window.color 来访问color 变量,以说明全局变量是window 对象的属性。而后,又使用window.sayColor()来直接经过window 对象调用这个函数,结果显示在了警告框中。
注:JavaScript中的window 对象除了扮演ECMAScript规定的Global 对象的角色外,还承担了不少别的任务。第8 章在讨论浏览器对象模型时将详细介绍window 对象。
另外一种取得Global 对象的方法是使用如下代码:
var global = function(){
return this;
}();
以上代码建立了一个当即调用的函数表达式,返回this 的值。如前所述,在没有给函数明确指定this 值的状况下(不管是经过将函数添加为对象的方法,仍是经过调用call()或apply()),this值等于Global 对象。而像这样经过简单地返回this 来取得Global 对象,在任何执行环境下都是可行的。第7 章将深刻讨论函数表达式。
Math对象
ECMAScript 还为保存数学公式和信息提供了一个公共位置,即Math 对象。与咱们在JavaScript 直接编写的计算功能相比,Math 对象提供的计算功能执行起来要快得多。Math 对象中还提供了辅助完成这些计算的属性和方法。
1. Math 对象的属性
Math 对象包含的属性大都是数学计算中可能会用到的一些特殊值。下表列出了这些属性。
虽然讨论这些值的含义和用途超出了本书范围,但你确实能够随时使用它们。
2. min()和max()方法
Math 对象还包含许多方法,用于辅助完成简单和复杂的数学计算。
其中,min()和max()方法用于肯定一组数值中的最小值和最大值。这两个方法均可以接收任意多个数值参数,以下面的例子所示。
var max = Math.max(3, 54, 32, 16);
alert(max); //54
var min = Math.min(3, 54, 32, 16);
alert(min); //3
对于三、5四、32 和16,Math.max()返回54,而Math.min()返回3。这两个方法常常用于避免多余的循环和在if 语句中肯定一组数的最大值。
要找到数组中的最大或最小值,能够像下面这样使用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
对于全部介于25 和26(不包括26)之间的数值,Math.ceil()始终返回26,由于它执行的是向上舍入。Math.round()方法只在数值大于等于25.5 时返回26;不然返回25。最后,Math.floor()对全部介于25 和26(不包括26)之间的数值都返回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)];
aler t(color); // 多是数组中包含的任何一个字符串
在这个例子中,传递给selectFrom()的第二个参数是数组的长度减1,也就是数组中最后一项的位置。
5. 其余方法
Math 对象中还包含其余一些与完成各类简单或复杂计算有关的方法,但详细讨论其中每个方法的细节及适用情形超出了本书的范围。下面咱们就给出一个表格,其中列出了这些没有介绍到的Math对象的方法。
虽然ECMA-262 规定了这些方法,但不一样实现可能会对这些方法采用不一样的算法。毕竟,计算某个值的正弦、余弦和正切的方式多种多样。也正由于如此,这些方法在不一样的实现中可能会有不一样的精度。