在学习JavaScript的一些总结和经验,供大家参考和学习,同时也欢迎大家参与讨论。
先放一张图,可以看出来 弱类型、强类型、动态类型、静态类型语言的区别。
强(数据)类型语言
定义:一旦一个变量被指定了某个数据类型,如果不经过强制转换,那么它就永远是这个数据类型了。比如你定义了一个整型变量a,那么我们不能将a当作字符串类型来处理处理。
弱(数据)类型语言
问题: 你描述一下为什么javascript是弱类型语言?
弱在哪里?体现在哪?
JavaScript 声明变量的时候并没有预先确定的类型(只是用var声明),变量的类型就是其值的类型,也就是说变量当前的类型由其值所决定。虽然弱类型的这种不需要预先确定类型的特性给我们带来了便利,同时也会给我们带来困扰。为了能充分利用该特性就必须掌握类型转换的原理。
例子1:
1 | var a = 1 + '2'; // a的值输出的是12,而这种情况在“强类型语言”中会报错的 |
例子2:我们var了一个a(它的类型由赋值等号后面的值决定),而在下面还可以对a进行随意修改
1 | var a = 0; |
等等等等。。。
显式(强)类型转换
Number()
先看一下例子:
1 | Number(undefined), //NaN |
从上面的例子我们可以得出Number运算符的转换规则:
- undefined 转换为 NaN
- null 转换为 0
- true 转换为 1,false 转换为 0
- 字符串
- 空格字符串转为0
- 非空字符串,并且内容为纯数字(包含进制与科学表示法)转成对应的数字
- 其余都是NaN,比如
Number('funcation(){}')或Number('AB')
- 数字 转换为 数字本身
对象(引用类型)
如果是对象{}、函数,则转换为 NaN
空数组 转换为 0,数组里只有一个数据并且这个数据能转成数字,则转成对应的数字,其它都转成NaN
String()
1 | String(null), //'null' |
从上面的例子我们可以得出String运算符的转换规则:
- 基本数据类型、null、undefined的结果就是给数据加上引号变成字符串
引用数据类型
如果是数组,结果为把所有中括号去掉,外面加个引号
如果是对象,结果为’[object Object]’(除了日期对象)
如果是函数,结果为在函数整体外面加个引号
Boolean()
1 | Boolean(undefined) // false |
从上面的例子我们可以得出Boolean运算符的转换规则:
除了下述 6 个值转换结果为 false,其他全部为 true:
undefined
null
-0或0或+0
NaN
‘’(空字符串)
在这讲一个额外的知识点Truthy:
在 JavaScript 中,truthy(真值)指的是在布尔值上下文中,转换后的值为真的值。所有值都是真值,除非它们被定义为 假值(即除 false、0、""、null、undefined 和 NaN 以外皆为真值)。
JavaScript 中的真值示例如下(将被转换为 true,if 后的代码段将被执行):
1 | if (true) |
接下来重点来了,那他们三个转换背后的原理是什么?
转换背后的原理
在JavaScript中每一个对象都有一个valueOf()和toString()方法
valueOf() 返回该对象对应的原始值
JavaScript的许多内置对象(Array、Function、String、Boolean、Number)都重写了该函数,以实现更适合自身的功能需要。因此,不同类型对象的valueOf()方法的返回值和返回值类型均可能不同。
| 对象 | 返回值 |
|---|---|
| Array | 返回数组对象本身。 |
| Boolean | 布尔值。 |
| Date | 存储的时间是从 1970 年 1 月 1 日午夜开始计的毫秒数 UTC。 |
| Function | 函数本身。 |
| Number | 数字值。 |
| Object | 对象本身。这是默认情况。 |
| String | 字符串值。 |
| Math 和 Error 对象没有 valueOf 方法。 |
toString 返回对象的字符串的表现形式
每个对象都有一个 toString() 方法,当对象被表示为文本值时或者当以期望字符串的方式引用对象时,该方法被自动调用。
这里先记住,valueOf() 和 toString() 在特定的场合下会自行调用。
| 对象 | 返回值 |
|---|---|
| Number | 数据转成字符串的形式 ,如: ‘123’ |
| Boolean | 数据转成字符串的形式 ,如: ‘true’、’false’ |
| String | 数据转成字符串的形式 ,如: ‘jsldkfjsl’ |
| Function | 在数据外面加了个引号 ,如: ‘function foo(){}’ |
| Object | “[object Object]” |
| Date | “Thu Jul 04 2019 11:53:31 GMT+0800 (中国标准时间)” 当前时间 |
Number方法背后的原理
- 调用对象的valueOf方法。如果返回原始类型的值,再使用Number函数,不再进行后续步骤。
- 如果valueOf方法返回的不是原始值,则调用toString方法。
- toString方法返回原始类型的值,则对该值使用Number函数,不再进行后续步骤。
- 如果toString方法后返回的依然不是原始值,就报错,抛出
TypeError异常(一般不会出现)
String方法背后的原理
- 调用对象的toString方法。如果返回原始类型的值,再使用String函数,不再进行后续步骤。
- 如果toString方法返回的不是原始值,则调用valueOf方法。
- valueOf方法返回原始类型的值,则对该值使用String函数,不再进行后续步骤。
- 如果valueOf方法后返回的依然不是原始值,就报错,抛出
TypeError异常(一般不会出现)
注意:两者的调用顺序是相反的
隐式类型转换
1 | /* |
== 两边发生的隐式转换
1 | /* |
逗号运算符
1 | console.log((1,2,3)); // 3 |
引用:
文章标题: 显式类型转换和隐式类型转换
文章作者: 王奕聪,QQ:1301842163
许可协议:
©署名-非商用-相同方式共享 4.0
