这是我参与8月更文挑战的第30天,活动详情查看: 8月更文挑战
3. Global 对象属性
Global 对象有很多属性,其中一些前面已经提到过了。像 undefined、NaN 和 Infinity 等特殊 值都是 Global 对象的属性。此外,所有原生引用类型构造函数,比如 Object 和 Function,也都是 Global 对象的属性。下表列出了所有这些属性。
属 性 | 说 明 |
---|---|
undefined | 特殊值 undefined |
NaN | 特殊值 NaN |
Infinity | 特殊值 Infinity |
Object | Object的构造函数 |
Array | Array的构造函数 |
Function | Function的构造函数 |
Boolean | Boolean的构造函数 |
String | String的构造函数 |
Number | Number的构造函数 |
Date | Date的构造函数 |
RegExp | RegExp的构造函数 |
Symbol | Symbol的构造函数 |
Error | Error的构造函数 |
EvalError | EvalError的构造函数 |
RangeError | RangeError的构造函数 |
ReferenceError | ReferenceError的构造函数 |
SyntaxError | SyntaxError的构造函数 |
TypeError | TypeError的构造函数 |
URIError | URIError的构造函数 |
4. window 对象
虽然 ECMA-262 没有规定直接访问 Global 对象的方式,但浏览器将 window 对象实现为 Global 对象的代理。因此,所有全局作用域中声明的变量和函数都变成了 window 的属性。来看下面的例子:
var color = "red";
function sayColor() {
console.log(window.color);
}
window.sayColor(); // "red"
这里定义了一个名为color的全局变量和一个名为sayColor()的全局函数。在sayColor()内部, 通过 window.color 访问了 color 变量,说明全局变量变成了 window 的属性。接着,又通过 window 对象直接调用了 window.sayColor()函数,从而输出字符串。
注意 window 对象在 JavaScript 中远不止实现了 ECMAScript 的 Global 对象那么简单。 关于 window 对象的更多介绍,请参考第 12 章
另一种获取 Global 对象的方式是使用如下的代码:
let global = function() {
return this;
}();
这段代码创建一个立即调用的函数表达式,返回了 this 的值。如前所述,当一个函数在没有明确 (通过成为某个对象的方法,或者通过 call()/apply())指定 this 值的情况下执行时,this 值等于 Global 对象。因此,调用一个简单返回 this 的函数是在任何执行上下文中获取 Global 对象的通用 方式。
5.4.2 Math
ECMAScript 提供了 Math 对象作为保存数学公式、信息和计算的地方。Math 对象提供了一些辅助 计算的属性和方法。
注意 Math 对象上提供的计算要比直接在 JavaScript 实现的快得多,因为 Math 对象上的 计算使用了 JavaScript 引擎中更高效的实现和处理器指令。但使用 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 的平方根 |
Math.SQRT2 | 2 的平方根 |
这些值的含义和用法超出了本书的范畴,但都是 ECMAScript 规范定义的,并可以在你需要时使用。
2. min()和 max()方法
Math 对象也提供了很多辅助执行简单或复杂数学计算的方法。
min()和 max()方法用于确定一组数值中的最小值和最大值。这两个方法都接收任意多个参数,如 下面的例子所示:
let max = Math.max(3, 54, 32, 16);
console.log(max); // 54
let min = Math.min(3, 54, 32, 16);
console.log(min); // 3
在 3、54、32 和 16 中,Math.max()返回 54,Math.min()返回 3。使用这两个方法可以避免使用 额外的循环和 if 语句来确定一组数值的最大最小值。
要知道数组中的最大值和最小值,可以像下面这样使用扩展操作符:
let values = [1, 2, 3, 4, 5, 6, 7, 8];
let max = Math.max(...val);
3. 舍入方法
接下来是用于把小数值舍入为整数的 4 个方法:Math.ceil()、Math.floor()、Math.round() 和 Math.fround()。这几个方法处理舍入的方式如下所述。
- Math.ceil()方法始终向上舍入为最接近的整数。
- Math.floor()方法始终向下舍入为最接近的整数。
- Math.round()方法执行四舍五入。
- Math.fround()方法返回数值最接近的单精度(32 位)浮点值表示。
以下示例展示了这些方法的用法:
console.log(Math.ceil(25.9)); // 26
console.log(Math.ceil(25.5)); // 26
console.log(Math.ceil(25.1)); // 26
console.log(Math.round(25.9)); // 26
console.log(Math.round(25.5)); // 26
console.log(Math.round(25.1)); // 25
console.log(Math.fround(0.4)); // 0.4000000059604645
console.log(Math.fround(0.5)); // 0.5
console.log(Math.fround(25.9)); // 25.899999618530273
console.log(Math.floor(25.9)); // 25
console.log(Math.floor(25.5)); // 25
console.log(Math.floor(25.1)); // 25
对于 25 和 26(不包含)之间的所有值,Math.ceil()都会返回 26,因为它始终向上舍入。 Math.round()只在数值大于等于 25.5 时返回 26,否则返回 25。最后,Math.floor()对所有 25 和 26(不包含)之间的值都返回 25。
4. random()方法
Math.random()方法返回一个 0~1 范围内的随机数,其中包含 0 但不包含 1。对于希望显示随机名 言或随机新闻的网页,这个方法是非常方便的。可以基于如下公式使用 Math.random()从一组整数中 随机选择一个数:
number = Math.floor(Math.random() * total_number_of_choices + first_possible_value)
这里使用了 Math.floor()方法,因为 Math.random()始终返回小数,即便乘以一个数再加上一 个数也是小数。因此,如果想从 1~10 范围内随机选择一个数,代码就是这样的:
let num = Math.floor(Math.random() * 10 + 1);
这样就有 10 个可能的值(110),其中最小的值是 1。如果想选择一个 210 范围内的值,则代码就 要写成这样:
let num = Math.floor(Math.random() * 9 + 2);
2~10 只有 9 个数,所以可选总数(total_number_of_choices)是 9,而最小可能的值 (first_possible_value)是 2。很多时候,通过函数来算出可选总数和最小可能的值可能更方便, 比如:
function selectFrom(lowerValue, upperValue) {
let choices = upperValue - lowerValue + 1;
return Math.floor(Math.random() * choices + lowerValue);
}
let num = selectFrom(2,10);
console.log(num); // 2~10 范围内的值,其中包含 2 和 10
这里的函数 selectFrom()接收两个参数:应该返回的最小值和最大值。通过将这两个值相减再加 1 得到可选总数,然后再套用上面的公式。于是,调用 selectFrom(2,10)就可以从 2~10(包含) 范围内选择一个值了。使用这个函数,从一个数组中随机选择一个元素就很容易,比如:
let colors = ["red", "green", "blue", "yellow", "black", "purple", "brown"];
let color = colors[selectFrom(0, colors.length-1)];
在这个例子中,传给 selecFrom()的第二个参数是数组长度减 1,即数组最大的索引值。
注意 Math.random()方法在这里出于演示目的是没有问题的。如果是为了加密而需要 生成随机数(传给生成器的输入需要较高的不确定性),那么建议使用 window.crypto. getRandomValues()。
5. 其他方法
Math 对象还有很多涉及各种简单或高阶数运算的方法。讨论每种方法的具体细节或者它们的适用 场景超出了本书的范畴。不过,下表还是总结了 Math 对象的其他方法。
方 法 | 说 明 |
---|---|
Math.abs(x) | 返回 x 的绝对值 |
Math.exp(x) | 返回 Math.E 的 x 次幂 |
Math.expm1(x) | 等于 Math.exp(x) - 1 |
Math.log(x) | 返回 x 的自然对数 |
Math.log1p(x) | 等于 1 + Math.log(x) |
Math.pow(x, power) | 返回 x 的 power 次幂 |
Math.hypot(...nums) | 返回 nums 中每个数平方和的平方根 |
Math.clz32(x) | 返回 32 位整数 x 的前置零的数量 |
Math.sign(x) | 返回表示 x 符号的 1、0、-0 或-1 |
Math.trunc(x) | 返回 x 的整数部分,删除所有小数 |
Math.sqrt(x) | 返回 x 的平方根 |
Math.cbrt(x) | 返回 x 的立方根 |
Math.acos(x) | 返回 x 的反余弦 |
Math.acosh(x) | 返回 x 的反双曲余弦 |
Math.asin(x) | 返回 x 的反正弦 |
Math.asinh(x) | 返回 x 的反双曲正弦 |
Math.atan(x) | 返回 x 的反正切 |
Math.atanh(x) | 返回 x 的反双曲正切 |
Math.atan2(y, x) | 返回 y/x 的反正切 |
Math.cos(x) | 返回 x 的余弦 |
Math.sin(x) | 返回 x 的正弦 |
Math.tan(x) | 返回 x 的正切 |
即便这些方法都是由 ECMA-262 定义的,对正弦、余弦、正切等计算的实现仍然取决于浏览器,因 为计算这些值的方式有很多种。结果,这些方法的精度可能因实现而异。
5.5 小结
JavaScript 中的对象称为引用值,几种内置的引用类型可用于创建特定类型的对象。
- 引用值与传统面向对象编程语言中的类相似,但实现不同。
- Date 类型提供关于日期和时间的信息,包括当前日期、时间及相关计算。
- RegExp 类型是 ECMAScript 支持正则表达式的接口,提供了大多数基础的和部分高级的正则表 达式功能。
JavaScript 比较独特的一点是,函数实际上是 Function 类型的实例,也就是说函数也是对象。因 为函数也是对象,所以函数也有方法,可以用于增强其能力。
由于原始值包装类型的存在,JavaScript 中的原始值可以被当成对象来使用。有 3 种原始值包装类 型:Boolean、Number 和 String。它们都具备如下特点。
- 每种包装类型都映射到同名的原始类型。
- 以读模式访问原始值时,后台会实例化一个原始值包装类型的对象,借助这个对象可以操作相 应的数据。
- 涉及原始值的语句执行完毕后,包装对象就会被销毁。
当代码开始执行时,全局上下文中会存在两个内置对象:Global 和 Math。其中,Global 对象在 大多数 ECMAScript 实现中无法直接访问。不过,浏览器将其实现为 window 对象。所有全局变量和函 数都是 Global 对象的属性。Math 对象包含辅助完成复杂计算的属性和方法。