原生函数
也叫JavaScript
的内建函数。常用的有:
String()
Number()
Boolean()
Array()
Object()
Function()
RegExp()
Date()
Error()
Symbol()——ES6新加入
封装对象包装
JavaScript
会自动为基本类型值包装,所以像一些.length
、.toString()
的属性和方法,在基本类型被字面量定义之后,也能拥有这些方法和属性。
特别注意在封装数字和布尔值后,用来进行判断时,会有一些疑惑:
var a = new Boolean(false);
if (!a) {
console.log("Oops"); // 执行不到这里
}
var b = new Number(0);
if(!b) {
console.log('Number'); // 执行不到这里
}
原生函数作为构造函数
当Array
构造函数只带一个数字参数时,这个参数为数组的预设长度,而非数组的第一个元素。
永远不要创建和使用空单元数组。
除非万不得已,否则尽量不要使用Object()
、Function()
、RegExp()
,直接使用字面量语法,其中RegExp()
和Function()
在需要动态定义时才比较有用。正则使用字面量语法的执行效率要高于使用构造函数,这和JavaScript
在执行前需要预编译有关。
Date()
和Error()
没有对应的常量形式,所以在代码中用的比较多。
ES6
新加入的基本数据类型——符号Symbol
。主要解决对象属性重名的问题,作为对象属性时,常规的对象属性遍历是无法获取Symbol
的,只能通过特殊的方法来获取——Object.getOwnPropertySymbols()
。所以常被用来作为类的私有方法。用来替代_
下划线前缀的属性。Symbol
由于其值的”唯一性“还可以用来消除魔术字符串。阮一峰老师的blog
上讲的很详细。
特殊的原生原型
typeof Function.prototype; // "function"
Function.prototype(); // 空函数!
RegExp.prototype.toString(); // "/(?:)/"————空正则表达式
"abc".match(RegExp.prototype); // [""]
Array.isArray(Array.prototype); // true
Array.prototype.push(1, 2, 3); // 3
Array.prototype; // [1, 2, 3]
强制类型转换
类型转换分为两种,一种发生在静态语法分析时;另一种则是发生在动态类型语言的运行时(runtime
),JavaScript
统称为强制类型转换。
强制类型转换总返回标量基本类型值,既简单值(如字符串、数字、boolean
等)。
值类型转换
隐式强制类型转换和显示强制类型转换是相对而言的:
var a = 42;
var b = a + ""; // 隐式
var c = String(a); // 显示
如果明白a + ""
是怎么回事,那么它也是显示的,如果不明白String(a)
是怎么回事,那么它也是隐式的。
抽象值操作(即“仅供内部使用的操作”)
ToString
处理非字符串到字符串的强制类型转换。
null --> "null"
undefined --> "undefined"
true --> "true"
极大极小的数字则转换为指数形式:
var a = 1.07 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000;
a.toString(); // "1.07e21"
普通对象,除非自定义,否则toString()
返回内部属性[[Class]]
的值。
var obj = { a: 1 };
obj.toString(); // "[object Object]"
数组的默认toString()
方法经过了重新定义,将所有单元字符串化以后再用","
连接起来:
let a = [1, 2, 3];
a.toString(); // 1,2,3
let b = [{ c: 1 }, { d: 2 }];
b.toString(); // [object Object],[object Object]
数组的toString
可以被显示调用,或者在需要字符串化时自动调用。
JSON字符串化
对象中如果定义了toJSON
方法,JSON
字符串化时会首先调用该方法,然后用它的返回值来进行序列化——toJSON
应该“返回一个能够被字符串化的安全的JSON
值”。
JSON.stringify
并不是强制类型转换,只是其中几种转换规则与ToString
相同:字符串、数字、布尔值和null
。
ToNumber
对象转换为数字分为3步:
- 检查该值是否有
valueOf()
方法,如果有,且返回基本类型值,则使用此基本类型值强制类型转换。 - 如果没有
valueOf()
方法,则检查是否有toString()
方法,有,且返回基本类型值,则同上。 - 如果以上两种方法都没有,则抛出
TypeError
错误。
ToBoolean
JavaScript
规范定义了一小撮可以被强制类型转换为false
的值:
undefined
null
false
+0、-0和NaN
""
但是JavaScript
规范并没有明确规定假值列表之外的都是真值,不过我们可以理解为假值列表以外的值都是真值。
假值对象
并不是说对象是假值,也不是说封装了假值的对象:
var a = new Boolean(false);
var b = new Number(0);
var c = new String("");
var d = Boolean(a && b && c); // true
而是浏览器在某些特定情况下,在常规JavaScript
语法基础上自己创建了一些外来(exotic
)值,这些就是“假值对象”。虽然代码中会出现这些假值对象,但是它并不属于JavaScript
语言范畴:
if(document.all) {...}
document.all
由DOM
提供给JavaScript
程序使用,以前曾是正真意义上的对象,可以强制转换城true
,但后来废止了,IE
也并不打算继续支持,但是许多程序中还有诸如以下的代码:
if(document.all) {/* it's IE */}
为了不再支持it's IE
中的代码,所以将document.all
作为假值来处理。
真值
假值列表以外的都是真值,值得注意的是:
var c = "''";
var d = Boolean(c); // true
因为""
是假值列表中唯一的字符串。
显示强制类型转换
字符串和数字之间的显示转换
var a = 42;
var b = String(a); // "42"
var c = "3.14";
var d = Number(c); // 3.14
String()
遵循前面讲过的ToString
规则,将值转换为字符串基本类型。Number()
遵循前面讲过的ToNumber
规则,将值转换为数字基本类型。
除了String()
和Number()
以外,还有其他方法可以实现字符串和数字之间的显式转换:
var a = 42;
var b = a.toString(); // "42"
var c = "3.14";
var d = +c; // 3.14
toString()
是显示的,但是其中也涉及到隐式转换,因为toString()
对于42
这种基本类型不适用,需要JavaScript
引擎自动为42
创建一个封装对象。
+c
是+
运算符的一元(unary
)形式(即只有一个操作数)。+
运算符显式地将c
转换为数字,而非数字加法运算。
注意:需要区分一元运算符+
和-
和递增++
和递减--
运算符。
1 - - 1; // 2
var d = 5 + +"3.14"; // 8.14
日期显示转换为数字
const t = new Date; // 构造函数没有参数的话,使用new运算可以不用()
+t // 1628564390661
~运算符
字位运算符只适用于32位整数,运算符会强制操作数使用32位格式,这里则是通过抽象操作ToInt32
实现的,ToInt32
则首先执行ToNumber
强制类型转换。
本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!