04 直接量及其相关对象
直接量是指不需要创建对象就可以直接使用的变量 。 ES 中的直接量主要有三种类型: 表示字符串的 string 类型 、 表示数字的 number 类型和表示 true/false 的 boolean 类型 。 对于直接量,在使用时直接将值赋给变量就可以了,例如下面的代码 。
1 | var str ="hello word"; |
当我们直接将值赋给变量后, ES 就会自动判断其类型,而且当参数值发生变化后(例如此例中的 flag ),其类型也会自动跟着发生变化,即 ES 是一种弱类型的语言。另外,对于数字类型来说,无论是整数还是小数都是 number 类型。
4.1 直接量的保存方式
之前在内存模型中介绍过,直接量直接使用两块内存来保存它们的名值对,而不像对象类型那样需要 3 块内存。明白了这一点我们就可以知道,直接量是各自保存各自的值,它们不会相互影响,例如下面的例子。
1 | var m = 5; |
这个例子中,虽然将 m 赋值给 n ,但只是将 m 的值赋给 n ,当 m 发生变化时, n 并没有发生变化,这一点和对象类型是不同的。如果是对象类型,那么赋值的时候是将对象的地址赋给新值,当对象中的属性发生变化时两个对象都会发生变化,例如下面的例子。
1 | var obj = {m:5}; |
在这个例子中, obj 和 newObj 使用的是同一个对象,当 obj 中的 m 属性发生变化时, newObj 中的 m 属性也会发生变化。
4.2 直接量的封包与解包
直接量是单个值,并不是对象,当然也就没有属性。但是在 ES 中,我们可以使用直接量来调用属性方法,例如下面的例子。
1 | function log(msg) { |
这个例子中,由 String 类型的变量 s 调用了 toUpperCase 、 substr 和 length 属性,分别用于将 s 的值变为大写、截取 s 的一部分及获取 s 的长度; number 类型的变量 n 调用了 toPrecision , toExponential 和 toLocaleString 方法,分别用于设置 n 的精度、将 n 转换为科学计数法,以及将 n 转换为本地数组表达格式; boolean 类型的 b 属性调用了 toString 方法,用于将 boolean 转换为 string 类型 。 既然直接量只是一个值而不是对象,那么它怎么可以调用属性方法呢?原来自有一种叫作自动封包/解包的功能 。 封包/解包对于熟悉 Java 的读者来说一定不会陌生(在 Java 中也称装箱/拆箱,它们的含义都一样),其作用是在程序执行过程中按照实际需要自动在直接量和其所对应的对象类型之间进行转化 。 将直接量转换为对应的对象进行处理叫作封包,反过来,将对象转换为直接量叫作解包 。 封包和解包都是 JS 引擎自动完成的,而且只是为了完成程序的执行而进行的暂时转换,并不会实际修改变量的类型。有了封包/解包我们就不需要考虑什么时候使用直接量什么时候使用对象了,而且也不需要担心变量类型会发生变化 。上面的例子就使用了封包功能,下面我们再来看一个使用到解包功能的例子 。
1 | var m = new Number(5); |
这个例子中,定义了对象类型的 m 变量,当对其进行加法计算时 m 会自动解包为直接量再进行计算,但是计算之后 m 的类型并不会变化,还是 object 类型。实际使用中我们很少直接使用直接量所对应的包装对象,所以封包功能使用得非常多,但是解包功能相对使用得就比较少了。
js类型转换
4.3 直接量的包装对象
直接量所对应的对象叫作包装对象, string 、 number 、 boolean 所对应的包装对象分别是 String 对象、 Number 对象和 Boolean 对象,它们都是 function 类型的对象。本节我们就来学习这三个对象。一个对象最重要的就是它所包含的属性,而 function 对象的属性又分为两大类,一类是它自身的属性,另一类是它创建的 object 类型实例对象的属性,创建的实例对象的属性又分为实例自己的属性和 function 的 prototype 的属性。学习 function 类型对象最重要的是学习两个方面的内容: function 作为函数的功能和它对应的属性。对于包装类型的对象来说,作为函数使用时的功能都是将传入的参数转换为 function 所对应的直接量,例如,使用如 String("abc") 可以新建值为 abc 的字符串类型的直接量等,其实和不使用函数的效果是一样的,所以学习包装类型对象主要是学习它所对应的属性。包装对象的属性和普通对象的属性没有什么区别,也是一共包括三部分: function 对象自身拥有的属性、创建的实例对象所拥有的属性和 function 的 prototype 属性对象中的属性。下面我们就从这三个方面分别学习这三个包装对象。
4.3.1 String 对象
String 对象是 function 类型的对象,对应的是字符串类型,可用来创建字符串类型的object 对象,例如, new String (” abc ”) ;就可以创建一个值为 abc 的字符串对象。最重要的还是它所对应的三种属性。
String 自身的属性
String 类型自身只有两个属性,一个是 prototype ,另一个是 fromCharCode 。对于 prototype 我们就不再解释了,企 omCharCode 方法的作用是创建由 Unicode 值所对应的字符组成的字符串,需要一个或多个参数,例如下面的例子。 vars= String . fromCharCode(97 , 98 , 99); console.log(s) ; // abc 在这个例子中,因为 97 、 98 、 99 所对应的 Unicode 值分别为 a 、 b 、 c ,所以创建出来的字符串 s 就是 abc 。
String.prototype.constructor:返回创建该字符串实例的函数,即String。String.prototype.length:返回字符串的长度,即字符串中的字符数。
String.prototype 中的属性
在 JavaScript 中,String.prototype 是一个对象,它包含所有字符串实例共享的属性和方法。以下是一些常见的 String.prototype 中的属性和方法:
String.prototype.charAt(index):返回指定索引处的字符。1
'hello'.charAt(1); // 'e'
String.prototype.charCodeAt(index):返回指定索引处字符的 Unicode 编码。1
'hello'.charCodeAt(1); // 101
String.prototype.codePointAt(pos):返回指定索引处字符的 Unicode 编码点。1
'a'.codePointAt(0); // 97
String.prototype.concat(str1, ..., strN):将一个或多个字符串连接到当前字符串的末尾,并返回新的字符串。1
'hello'.concat(' ', 'world'); // 'hello world'
String.prototype.endsWith(searchString, length):判断当前字符串是否以指定的子字符串结束。1
'hello world'.endsWith('world'); // true
String.prototype.includes(searchString, position):判断当前字符串是否包含指定的子字符串。1
'hello world'.includes('world'); // true
String.prototype.indexOf(searchValue, fromIndex):返回指定值首次出现的索引,如果不存在则返回 -1。1
'hello world'.indexOf('world'); // 6
String.prototype.lastIndexOf(searchValue, fromIndex):返回指定值最后一次出现的索引,如果不存在则返回 -1。1
'hello world'.lastIndexOf('l'); // 9
String.prototype.localeCompare(that):根据本地环境的排序规则,比较两个字符串。1
'a'.localeCompare('b'); // -1
String.prototype.match(regexp):对字符串执行匹配搜索,并将匹配的结果作为数组返回。1
'hello world'.match(/world/); // ['world', index: 6, input: 'hello world', groups: undefined]
String.prototype.matchAll(regexp):返回一个包含所有成功匹配结果的迭代器。1
2
3
4let matches = 'hello world'.matchAll(/l/g);
for (let match of matches) {
console.log(match); // ['l', index: 2, input: 'hello world', groups: undefined]
}String.prototype.normalize(form):返回调用字符串的 Unicode 正规形式。1
'a\u0301'.normalize(); // 'á'
String.prototype.padEnd(targetLength, padString):将当前字符串填充到指定长度。1
'hello'.padEnd(10, ' '); // 'hello '
String.prototype.padStart(targetLength, padString):将当前字符串从开头填充到指定长度。1
'hello'.padStart(10, ' '); // ' hello'
String.prototype.repeat(count):返回一个新字符串,表示将当前字符串重复指定次数。1
'hello'.repeat(2); // 'hellohello'
String.prototype.replace(searchValue, replaceValue):在字符串中查找匹配项,然后使用新的子字符串替换匹配项。1
'hello world'.replace('world', 'everyone'); // 'hello everyone'
String.prototype.search(regexp):执行匹配搜索,返回匹配项的索引,如果未找到则返回 -1。1
'hello world'.search(/world/); // 6
String.prototype.slice(beginIndex, endIndex):提取字符串的某个部分,并返回一个新字符串。1
'hello world'.slice(6, 11); // 'world'
String.prototype.split(separator, limit):使用指定的分隔符字符串将一个 String 对象分割成子字符串数组。1
'hello world'.split(' '); // ['hello', 'world']
String.prototype.startsWith(searchString, position):判断当前字符串是否以指定的子字符串开头。1
'hello world'.startsWith('hello'); // true
String.prototype.substring(start, end):返回一个字符串在开始索引到结束索引之间的一个子集。1
'hello world'.substring(6, 11); // 'world'
String.prototype.toLowerCase():将字符串转换为小写。1
'HELLO WORLD'.toLowerCase(); // 'hello world'
String.prototype.toLocaleLowerCase(locales):根据本地环境将字符串转换为小写。1
'HELLO WORLD'.toLocaleLowerCase(); // 'hello world'
String.prototype.toUpperCase():将字符串转换为大写。1
'hello world'.toUpperCase(); // 'HELLO WORLD'
String.prototype.toLocaleUpperCase(locales):根据本地环境将字符串转换为大写。1
'hello world'.toLocaleUpperCase(); // 'HELLO WORLD'
String.prototype.trim():去除字符串两端的空白字符。1
' hello world '.trim(); // 'hello world'
String.prototype.trimStart():去除字符串开头的空白字符。1
' hello world'.trimStart(); // 'hello world'
String.prototype.trimEnd():去除字符串末尾的空白字符。1
'hello world '.trimEnd(); // 'hello world'
String.prototype.valueOf():返回字符串的原始值。这些方法和属性为字符串的处理和操作提供了强大的支持,使得字符串的处理更加灵活和高效。1
'hello world'.valueOf(); // 'hello world'
String 创建的对象实例的属性
String 创建的实例对象一共有两个属性,一个是 length 属性,它代表字符串的长度;另外一个属性类似于数组,属性名为 0 到 length - 1,属性值为序号所对应的字符,例如下面的例子。
1 | var s = "www.excelib.com"; |
使用第二个属性我们就可以把字符串当作字符数组来使用了 。
4.3.2 Number 对象
Number 对象是 function 类型的对象,对应的是数字类型,可用来创建数字类型的。同 ect 对象,例如, new Number(123)就可以创建一个值为 123 的数字实例对象。最重要的依然是它所对应的三种属性。
Number 自身的属性
JavaScript 中的 Number 对象提供了许多有用的属性和方法。这些属性和方法可以帮助你进行各种数值操作和检查。以下是一些 Number 对象自身的属性:
- Number.MAX_VALUE
- 表示 JavaScript 中最大的正数,大约是
1.7976931348623157e+308。 - 用于检查数值是否超过了 JavaScript 能表示的最大范围。
1
console.log(Number.MAX_VALUE); // 1.7976931348623157e+308
- 表示 JavaScript 中最大的正数,大约是
- Number.MIN_VALUE
- 表示 JavaScript 中最小的正数,大约是
5e-324。 - 用于检查数值是否接近 JavaScript 能表示的最小正数。
1
console.log(Number.MIN_VALUE); // 5e-324
- 表示 JavaScript 中最小的正数,大约是
- Number.MAX_SAFE_INTEGER
- 表示 JavaScript 中最大的安全整数,即
2^53 - 1,等于9007199254740991。 - 安全整数是指在这个范围内,整数的表示是精确的。
1
console.log(Number.MAX_SAFE_INTEGER); // 9007199254740991
- 表示 JavaScript 中最大的安全整数,即
- Number.MIN_SAFE_INTEGER
- 表示 JavaScript 中最小的安全整数,即
-2^53 + 1,等于-9007199254740991。 - 与
Number.MAX_SAFE_INTEGER一起,用于检查整数是否在安全范围内。
1
console.log(Number.MIN_SAFE_INTEGER); // -9007199254740991
- 表示 JavaScript 中最小的安全整数,即
- Number.POSITIVE_INFINITY
- 表示正无穷大。
- 用于表示一个数值超过了
Number.MAX_VALUE。
1
console.log(Number.POSITIVE_INFINITY); // Infinity
- Number.NEGATIVE_INFINITY
- 表示负无穷大。
- 用于表示一个数值小于
Number.MIN_VALUE且为负数。
1
console.log(Number.NEGATIVE_INFINITY); // -Infinity
- Number.NaN
- 表示“非数字”值。
- 用于表示一个数值是无效的或不是数字。
1
console.log(Number.NaN); // NaN
以下是一些使用这些属性的示例:
1 | // 检查数值是否在安全整数范围内 |
这些属性在处理数值时非常有用,可以帮助你确保数值在合理的范围内,避免一些常见的数值问题。
Number.prototype 的属性
Number.prototype 是一个对象,它包含所有数字实例共享的属性和方法。以下是一些常见的 Number.prototype 中的属性和方法:
属性
Number.prototype.constructor:返回创建该数字实例的函数,即Number。1
console.log((123).constructor === Number); // true
方法
Number.prototype.toExponential(fractionDigits):将数字转换为指数表示法。1
2console.log((123).toExponential()); // "1.23e+2"
console.log((123).toExponential(1)); // "1.2e+2"Number.prototype.toFixed(fractionDigits):将数字格式化为指定小数位数的字符串。1
2console.log((123.456).toFixed(2)); // "123.46"
console.log((123.456).toFixed(0)); // "123"Number.prototype.toPrecision(precision):将数字格式化为指定精度的字符串。1
2console.log((123.456).toPrecision(5)); // "123.46"
console.log((123.456).toPrecision(2)); // "1.2e+2"Number.prototype.toString(radix):将数字转换为字符串,可以指定进制。1
2
3console.log((123).toString()); // "123"
console.log((123).toString(16)); // "7b"
console.log((123).toString(2)); // "1111011"Number.prototype.valueOf():返回数字的原始值。1
console.log((123).valueOf()); // 123
静态属性
Number.EPSILON:表示 1 与大于 1 的最小浮点数之间的差异,用于精度比较。1
console.log(Number.EPSILON); // 2.220446049250313e-16
Number.MAX_SAFE_INTEGER:表示 JavaScript 中最大的安全整数(2^53 - 1)。1
console.log(Number.MAX_SAFE_INTEGER); // 9007199254740991
Number.MIN_SAFE_INTEGER:表示 JavaScript 中最小的安全整数(-(2^53 - 1))。1
console.log(Number.MIN_SAFE_INTEGER); // -9007199254740991
Number.MAX_VALUE:表示 JavaScript 中最大的数值。1
console.log(Number.MAX_VALUE); // 1.7976931348623157e+308
Number.MIN_VALUE:表示 JavaScript 中最小的正值。1
console.log(Number.MIN_VALUE); // 5e-324
Number.NaN:表示“非数字”值。1
console.log(Number.NaN); // NaN
Number.NEGATIVE_INFINITY:表示负无穷大。1
console.log(Number.NEGATIVE_INFINITY); // -Infinity
Number.POSITIVE_INFINITY:表示正无穷大。1
console.log(Number.POSITIVE_INFINITY); // Infinity
静态方法
Number.isFinite(value):判断一个值是否为有限数。1
2console.log(Number.isFinite(123)); // true
console.log(Number.isFinite(Infinity)); // falseNumber.isInteger(value):判断一个值是否为整数。1
2console.log(Number.isInteger(123)); // true
console.log(Number.isInteger(123.456)); // falseNumber.isNaN(value):判断一个值是否为 NaN。1
2console.log(Number.isNaN(NaN)); // true
console.log(Number.isNaN(123)); // falseNumber.isSafeInteger(value):判断一个值是否为安全整数。1
2console.log(Number.isSafeInteger(123)); // true
console.log(Number.isSafeInteger(9007199254740992)); // falseNumber.parseFloat(value):将一个值解析为浮点数。1
2console.log(Number.parseFloat('123.456')); // 123.456
console.log(Number.parseFloat('abc')); // NaNNumber.parseInt(value):将一个值解析为整数。这些属性和方法为数字的处理和操作提供了强大的支持,使得数字的处理更加灵活和高效。1
2console.log(Number.parseInt('123.456')); // 123
console.log(Number.parseInt('abc')); // NaN
Number 创建的实例对象的属性
Number 创建的实例对象没有自己的命名属性。
4.3.3 Boolean 对象
Boolean 对象是 function 类型的对象,对应的是布尔类型,可用来创建布尔类型的。同 ect 实例对象。例如, new ‘ Boolean (true )就可以创建一个值为 true 的布尔类型实例对象。 Boolean 对象非常简单。
Boolean 自身的属性
Boolean 作为对象时自身只有一个 prototype 属性 。 prototype 我们已经非常熟悉了,这里 就不再重述了 。
Boolean. prototype 的属性
Boolean 的 prototype 一共有三个属性: constructor 、 to String 和 valueOf 。 constructor 指向 Boolean 本身, to String 和 valueOf 都返回实例对象的值,但它们的类型不一样, to String 返回 s位ing 类型,而 valueOf 返回 boolean 类型。下面来看个例子。
1 | var b = new Boolean(true); |
Boolean 创建的实例对象的属性
Boolean 创建的对象实例自身不包含命名属性。
如何在浏览器申查看对象的属性
本节介绍的包装对象中的属性主要是标准中规定的属性,但不同的浏览器除了实现标准中的属性外,还可能会添加自己特有的属性,我们可以使用 Object 的 getOwnPropertyNames 方法来获取当前浏览器中对象自身的所有属性。对于 function 类型的对象,我们需要获取三种类型的属性:
- function 自身的属性
- function.prototype 包含的属性
- 使用 function 创建的实例对象自身所包含的属性
这三种属性都可以通过Object 的 getOwnPropertyNames 方法来获取。例如,可以通过下面的代码来获取 String 象的三种类型的属性。
1 | console.log(Object.getOwnPropertyNames(String)) |
!Pasted image 20250114181139.png
通过上述方法可以获取当前浏览器中某个具体 function 对象的相关属性 。 对于所有 function 类型的对象都可以使用这个方法 , 包括 Object 对象和浏览器中的 Window 对象 。 注意 Window 对象不可以用来创建新的实 例对象 。