一、值属性
(1)Infinity
Infinity 是全局对象(global object)的一个属性,即它是一个全局变量。Infinity 的初始值是 Number.POSITIVE_INFINITY。Infinity(正无穷大)大于任何值。该值和数学意义上的无穷大很像,例如任何正值乘以 Infinity 为 Infinity, 任何数值除以 Infinity 为 0(注意,这里说的是正数乘以Infinity 为 Infinity!Infinity * 0 为NaN
console.log(Infinity ); /* Infinity */
console.log(Infinity + 1 ); /* Infinity */
console.log(Math.pow(10, 1000)); /* Infinity */
console.log(Math.log(0) ); /* -Infinity */
console.log(1 / Infinity ); /* 0 */
(2)NaN
全局属性 NaN 的值表示不是一个数字(Not-A-Number)NaN 属性的初始值就是 NaN,和 Number.NaN 的值一样。在现代浏览器中(ES5中), NaN 属性是一个不可配置(non-configurable),不可写(non-writable)的属性。但在ES3中,这个属性的值是可以被更改的,但是也应该避免覆盖。
- NaN如果通过 == 、 != 、 === 、以及 !==与其他任何值比较都将不相等 – 包括与其他 NAN值进行比较。必须使用 Number.isNaN() 或 isNaN() 函数。在执行自比较之中:NaN,也只有NaN,比较之中不等于它自己
NaN === NaN; // false
Number.NaN === NaN; // false
isNaN(NaN); // true
isNaN(Number.NaN); // true
function valueIsNaN(v) { return v !== v; }
valueIsNaN(1); // false
valueIsNaN(NaN); // true
valueIsNaN(Number.NaN); // true
- 注意isNaN()和Number.isNaN()之间的区别:如果当前值是NaN,或者将其强制转换为数字后将是NaN,则前者将返回true。而后者仅当值当前为NaN时才为true:
isNaN('hello world'); // true
Number.isNaN('hello world'); // false
(3)undefined
undefined是全局对象的一个属性。也就是说,它是全局作用域的一个变量。undefined的最初值就是原始数据类型undefined
一个没有被赋值的变量的类型是undefined。如果方法或者是语句中操作的变量没有被赋值,则会返回undefined
- 严格相等和undefined
你可以使用undefined和严格相等或不相等操作符来决定一个变量是否拥有值。在下面的代码中,变量x是未定义的,if 语句的求值结果将是true
var x;
if (x === undefined) {
// 执行这些语句
} else {
// 这些语句不会被执行
}
注意:这里是必须使用严格相等操作符(=)而不是标准相等操作符(),因为 x == undefined 会检查x是不是null,但是严格相等不会检查(有点饶人,其实 === 会严格判断双方的类型、值等是否相等)。null不等同于undefined。
- Typeof 操作符和undefined
使用 typeof的原因是它不会在一个变量没有被声明的时候抛出一个错误。
// 这里没有声明y
if(typeof y === 'undefined') { // 没有错误,执行结果为true
console.log("y is " + typeof y ) // y is undefined
}
if(y === undefined) { // ReferenceError: y is not defined
(4)globalThis
全局属性 globalThis 包含全局的 this 值,类似于全局对象(global object)。
globalThis 提供了一个标准的方式来获取不同环境下的全局 this 对象(也就是全局对象自身)。不像 window 或者 self 这些属性,它确保可以在有无窗口的各种环境下正常工作。所以,你可以安心的使用 globalThis,不必担心它的运行环境。为便于记忆,你只需要记住,全局作用域中的 this 就是 globalThis。
function canMakeHTTPRequest() {
return typeof globalThis.XMLHttpRequest === 'function';
}
console.log(canMakeHTTPRequest());
// expected output (in a browser): true
二、函数属性
全局函数可以直接调用,不需要在调用时指定所属对象,执行结束后会将结果直接返回给调用者。
1、eval()
eval() 函数会将传入的字符串当做 JavaScript 代码进行执行
一个表示 JavaScript 表达式、语句或一系列语句的字符串。表达式可以包含变量与已存在对象的属性。
返回字符串中代码的返回值。如果返回值为空,则返回 undefined。
eval() 是全局对象的一个函数属性。
如果你间接的使用 eval(),比如通过一个引用来调用它,而不是直接的调用 eval。 从 ECMAScript 5 起,它工作在全局作用域下,而不是局部作用域中。这就意味着,例如,下面的代码的作用声明创建一个全局函数,并且 eval 中的这些代码在执行期间不能在被调用的作用域中访问局部变量。
function test() {
var x = 2, y = 4;
console.log(eval('x + y')); // 直接调用,使用本地作用域,结果是 6
var geval = eval; // 等价于在全局作用域调用
console.log(geval('x + y')); // 间接调用,使用全局作用域,throws ReferenceError 因为`x`未定义
(0, eval)('x + y'); // 另一个间接调用的例子
}
eval() 通常比其他替代方法更慢,因为它必须调用 JS 解释器,而许多其他结构则可被现代 JS 引擎进行优化。
eval 执行一串 JavaScript 语句
var x = 5;
var str = "if (x == 5) {console.log('z is 42'); z = 42;} else z = 0;";
console.log('z is ', eval(str));
eval 返回最后一个表达式的值。
var str = 'if ( a ) { 1 + 1; } else { 1 + 2; }';
var a = true;
var b = eval(str); // returns 2
console.log('b is : ' + b);
a = false;
b = eval(str); // returns 3
console.log('b is : ' + b);
eval 中函数作为字符串被定义需要“(”和“)”作为前缀和后缀
var fctStr1 = 'function a() {}'
var fctStr2 = '(function a() {})'
var fct1 = eval(fctStr1) // 返回undefined
var fct2 = eval(fctStr2) // 返回一个函数
2、uneval()
函数创建一个代表对象的源代码的字符串。
注意:无法通过此方法获取对象的 JSON 形式。
var a = 1;
uneval(a); // returns a String containing 1
var b = "1";
uneval(b) // returns a String containing "1"
uneval(function foo(){}); // returns "(function foo(){})"
var a = uneval(function foo(){return 'hi'});
var foo = eval(a);
foo(); // returns "hi"
3、isFinite()
函数用来判断被传入的参数值是否为一个有限数值(finite number)。你可以用这个方法来判定一个数字是否是有限数字。isFinite 方法检测它参数的数值。如果参数是 NaN,正无穷大或者负无穷大,会返回false,其他返回 true。
isFinite(Infinity); // false
isFinite(NaN); // false
isFinite(-Infinity); // false
isFinite(0); // true
isFinite(2e64); // true, 在更强壮的Number.isFinite(null)中将会得到false
isFinite("0"); // true, 在更强壮的Number.isFinite('0')中将会得到false
4、isNaN()
函数用来确定一个值是否为NaN 。注:isNaN函数内包含一些非常有趣的规则;你也可以使用 ECMAScript 2015 中定义的 Number.isNaN() 来判断,如果给定值为 NaN则返回值为true;否则为false。
NaN值的产生
当算术运算返回一个未定义的或无法表示的值时,NaN就产生了。但是,NaN并不一定用于表示某些值超出表示范围的情况。将某些不能强制转换为数值的非数值转换为数值的时候,也会得到NaN。
例如,0 除以0会返回NaN —— 但是其他数除以0则不会返回NaN。
如果isNaN函数的参数不是Number类型, isNaN函数会首先尝试将这个参数转换为数值,然后才会对转换后的结果是否是NaN进行判断
isNaN(NaN); // true
isNaN(undefined); // true
isNaN({}); // true
isNaN(true); // false
isNaN(null); // false
isNaN(37); // false
// strings
isNaN("37"); // false: 可以被转换成数值37
isNaN("37.37"); // false: 可以被转换成数值37.37
isNaN("37,5"); // true
isNaN('123ABC'); // true: parseInt("123ABC")的结果是 123, 但是Number("123ABC")结果是 NaN
isNaN(""); // false: 空字符串被转换成0
isNaN(" "); // false: 包含空格的字符串被转换成0
// dates
isNaN(new Date()); // false
isNaN(new Date().toString()); // true
isNaN("blabla") // true: "blabla"不能转换成数值
// 转换成数值失败, 返回NaN
5、parseFloat()
函数解析一个参数(必要时先转换为字符串)并返回一个浮点数。给定值被解析成浮点数。如果给定值不能被转换成数值,则会返回 NaN。
如果 parseFloat 在解析过程中遇到了正号(+)、负号(- U+002D HYPHEN-MINUS)、数字(0-9)、小数点(.)、或者科学记数法中的指数(e 或 E)以外的字符,则它会忽略该字符以及之后的所有字符,返回当前已经解析到的浮点数。
第二个小数点的出现也会使解析停止(在这之前的字符都会被解析)。
参数首位和末位的空白符会被忽略。
如果参数字符串的第一个字符不能被解析成为数字,则 parseFloat 返回 NaN。
parseFloat 也可以解析并返回 Infinity。
parseFloat解析 BigInt 为 Numbers, 丢失精度。因为末位 n 字符被丢弃。
都返回3.14
parseFloat(3.14);
parseFloat('3.14');
parseFloat(' 3.14 ');
parseFloat('314e-2');
parseFloat('0.0314E+2');
parseFloat('3.14some non-digit characters');
parseFloat({ toString: function() { return "3.14" } });
将返回NaN
parseFloat("FF2")
返回 900719925474099300,当整数太大以至于不能被转换时将失去精度。
parseFloat(900719925474099267n);
parseFloat('900719925474099267n');
6、parseInt
parseInt(string, radix); 解析一个字符串并返回指定基数的十进制整数, radix 是2-36之间的整数,表示被解析字符串的基数。
string
要被解析的值。如果参数不是一个字符串,则将其转换为字符串(使用 ToString 抽象操作)。字符串开头的空白符将会被忽略。
radix 可选
从 2 到 36,表示字符串的基数。例如指定 16 表示被解析值是十六进制数。请注意,10不是默认值!
以下例子均返回15:
parseInt("0xF", 16);
parseInt("F", 16);
parseInt("17", 8);
parseInt(021, 8);
parseInt("015", 10); // parseInt(015, 10); 返回 13
parseInt(15.99, 10);
parseInt("15,123", 10);
parseInt("FXX123", 16);
parseInt("1111", 2);
parseInt("15 * 3", 10);
parseInt("15e2", 10);
parseInt("15px", 10);
parseInt("12", 13);
以下例子均返回 NaN:
parseInt("Hello", 8); // 根本就不是数值
parseInt("546", 2); // 除了“0、1”外,其它数字都不是有效二进制数字
7、decodeURI()
函数能解码由encodeURI 创建或其它流程得到的统一资源标识符(URI)。
const uri = 'https://mozilla.org/?x=шеллы';
const encoded = encodeURI(uri);
console.log(encoded);
// expected output: "https://mozilla.org/?x=%D1%88%D0%B5%D0%BB%D0%BB%D1%8B"
try {
console.log(decodeURI(encoded));
// expected output: "https://mozilla.org/?x=шеллы"
} catch (e) { // catches a malformed URI
console.error(e);
}
8、decodeURIComponent()
方法用于解码由 encodeURIComponent 方法或者其它类似方法编码的部分统一资源标识符(URI)。
try {
var a = decodeURIComponent('%E0%A4%A');
} catch(e) {
console.error(e);
}
// URIError: malformed URI sequence
9、encodeURI()
函数通过将特定字符的每个实例替换为一个、两个、三或四转义序列来对统一资源标识符 (URI) 进行编码 (该字符的 UTF-8 编码仅为四转义序列)由两个 “代理” 字符组成)。
encodeURI 会替换所有的字符,但不包括以下字符,即使它们具有适当的UTF-8转义序列:
类型 包含
保留字符 ; , / ? : @ & = + $
非转义的字符 字母 数字 - _ . ! ~ * ’ ( )
数字符号 #
10、encodeURIComponent()
函数通过将一个,两个,三个或四个表示字符的UTF-8编码的转义序列替换某些字符的每个实例来编码 URI (对于由两个“代理”字符组成的字符而言,将仅是四个转义序列) 。
不转义的字符:
A-Z a-z 0-9 - _ . ! ~ * ’ ( )
var set1 = ";,/?:@&=+$"; // 保留字符
var set2 = "-_.!~*'()"; // 不转义字符
var set3 = "#"; // 数字标志
var set4 = "ABC abc 123"; // 字母数字字符和空格
console.log(encodeURI(set1)); // ;,/?:@&=+$
console.log(encodeURI(set2)); // -_.!~*'()
console.log(encodeURI(set3)); // #
console.log(encodeURI(set4)); // ABC%20abc%20123 (the space gets encoded as %20)
console.log(encodeURIComponent(set1)); // %3B%2C%2F%3F%3A%40%26%3D%2B%24
console.log(encodeURIComponent(set2)); // -_.!~*'()
console.log(encodeURIComponent(set3)); // %23
console.log(encodeURIComponent(set4)); // ABC%20abc%20123 (the space gets encoded as %20)