js笔记——js数据类型转换

JavaScript是一种动态类型语言,变量是没有类型的,可以随时赋予任意值。但是,数据本身和各种运算是有类型的,因此运算时变量需要转换类型。大多数情况下,这种数据类型转换是自动的,但是有时也需要手动强制转换。

强制转换

强制转换主要指使用Number、String和Boolean三个构造函数,手动将各种类型的值,转换成数字、字符串或者布尔值。

Number函数:强制转换成数值

使用Number函数,可以将任意类型的值转化成数字。

(1)原始类型值的转换规则

  • 数值:转换后还是原来的值。
  • 字符串:如果可以被解析为数值,则转换为相应的数值,否则得到NaN。空字符串转为0。
  • 布尔值:true转成1,false转成0。
  • undefined:转成NaN。
  • null:转成0。
Number("324") // 324

Number("324abc") // NaN

Number("") // 0

Number(false) // 0

Number(undefined) // NaN

Number(null) // 0

Number函数将字符串转为数值,要比parseInt函数严格很多。基本上,只要有一个字符无法转成数值,整个字符串就会被转为NaN。


parseInt('011') // 9
parseInt('42 cats') // 42
parseInt('0xcafebabe') // 3405691582

Number('011') // 11
Number('42 cats') // NaN
Number('0xcafebabe') // 3405691582

上面代码比较了Number函数和parseInt函数,区别主要在于parseInt逐个解析字符,而Number函数整体转换字符串的类型。另外,Number会忽略八进制的前导0,而parseInt不会。

Number函数会自动过滤一个字符串前导和后缀的空格。


Number('\t\v\r12.34\n ')

(2)对象的转换规则

对象的转换规则比较复杂。

  1. 先调用对象自身的valueOf方法,如果该方法返回原始类型的值(数值、字符串和布尔值),则直接对该值使用Number方法,不再进行后续步骤。
  2. 如果valueOf方法返回复合类型的值,再调用对象自身的toString方法,如果toString方法返回原始类型的值,则对该值使用Number方法,不再进行后续步骤。
  3. 如果toString方法返回的是复合类型的值,则报错。

Number({a:1})
// NaN

上面代码等同于


if (typeof {a:1}.valueOf() === 'object'){
    Number({a:1}.toString());
} else {
    Number({a:1}.valueOf());
}

上面代码的valueOf方法返回对象本身({a:1}),所以对toString方法的返回值“[object Object]”使用Number方法,得到NaN。

如果toString方法返回的不是原始类型的值,结果就会报错。


var obj = {
    valueOf: function () {
            console.log("valueOf");
            return {};
    },
    toString: function () {
            console.log("toString");
            return {};
    }
};

Number(obj)
// TypeError: Cannot convert object to primitive value

上面代码的valueOf和toString方法,返回的都是对象,所以转成数值时会报错。

从上面的例子可以看出,valueOf和toString方法,都是可以自定义的。


Number({valueOf:function (){return 2;}})
// 2

Number({toString:function(){return 3;}})
// 3

Number({valueOf:function (){return 2;},toString:function(){return 3;}})
// 2

上面代码对三个对象使用Number方法。第一个对象返回valueOf方法的值,第二个对象返回toString方法的值,第三个对象表示valueOf方法先于toString方法执行。

String函数:强制转换成字符串

使用String函数,可以将任意类型的值转化成字符串。规则如下:

(1)原始类型值的转换规则

  • 数值:转为相应的字符串。
  • 字符串:转换后还是原来的值。
  • 布尔值:true转为“true”,false转为“false”。
  • undefined:转为“undefined”。
  • null:转为“null”。

String(123) // "123"

String("abc") // "abc"

String(true) // "true"

String(undefined) // "undefined"

String(null) // "null"

(2)对象的转换规则

如果要将对象转为字符串,则是采用以下步骤。

  1. 先调用toString方法,如果toString方法返回的是原始类型的值,则对该值使用String方法,不再进行以下步骤。
  2. 如果toString方法返回的是复合类型的值,再调用valueOf方法,如果valueOf方法返回的是原始类型的值,则对该值使用String方法,不再进行以下步骤。
  3. 如果valueOf方法返回的是复合类型的值,则报错。

String方法的这种过程正好与Number方法相反。


String({a:1})
// "[object Object]"

上面代码相当于下面这样。


String({a:1}.toString())
// "[object Object]"

如果toString方法和valueOf方法,返回的都不是原始类型的值,则String方法报错。


var obj = {
    valueOf: function () {
            console.log("valueOf");
            return {};
    },
    toString: function () {
            console.log("toString");
            return {};
    }
};

String(obj)
// TypeError: Cannot convert object to primitive value

下面是一个自定义toString方法的例子。


String({toString:function(){return 3;}})
// "3"

String({valueOf:function (){return 2;}})
// "[object Object]"

String({valueOf:function (){return 2;},toString:function(){return 3;}})
// "3"

上面代码对三个对象使用String方法。第一个对象返回toString方法的值(数值3),然后对其使用String方法,得到字符串“3”;
第二个对象返回的还是toString方法的值("[object
Object]"),这次直接就是字符串;第三个对象表示toString方法先于valueOf方法执行。

Boolean函数:强制转换成布尔值

使用Boolean函数,可以将任意类型的变量转为布尔值。

(1)原始类型值的转换方法

以下六个值的转化结果为false,其他的值全部为true。

  • undefined
  • null
  • -0
  • +0
  • NaN
  • ''(空字符串)

Boolean(undefined) // false

Boolean(null) // false

Boolean(0) // false

Boolean(NaN) // false

Boolean('') // false

(2)对象的转换规则

所有对象的布尔值都是true,甚至连false对应的布尔对象也是true。


Boolean(new Boolean(false))
// true

请注意,空对象{}和空数组[]也会被转成true。


Boolean([]) // true

Boolean({}) // true

自动转换

当遇到以下几种情况,JavaScript会自动转换数据类型:

  • 不同类型的数据进行互相运算;
  • 对非布尔值类型的数据求布尔值;
  • 对非数值类型的数据使用一元运算符(即“+”和“-”)。

自动转换为布尔值

当JavaScript遇到预期为布尔值的地方(比如if语句的条件部分),就会将非布尔值的参数自动转换为布尔值。它的转换规则与上面的“强制转换成布尔值”的规则相同,也就是说,在预期为布尔值的地方,系统内部会自动调用Boolean方法。

因此除了以下六个值,其他都是自动转为true:

  • undefined
  • null
  • -0
  • +0
  • NaN
  • ''(空字符串)

if (!undefined && !null && !0 && !NaN && !''){
    console.log('true');
}
// true

自动转换为字符串

当JavaScript遇到预期为字符串的地方,就会将非字符串的数据自动转为字符串,转换规则与“强制转换为字符串”相同。

字符串的自动转换,主要发生在加法运算时。当一个值为字符串,另一个值为非字符串,则后者转为字符串。


'5' + 1 // '51'
'5' + true // "5true"
'5' + false // "5false"
'5' + {} // "5[object Object]"
'5' + [] // "5"
'5' + function (){} // "5function (){}"
'5' + undefined // "5undefined"
'5' + null // "5null"

自动转换为数值

当JavaScript遇到预期为数值的地方,就会将参数值自动转换为数值,转换规则与“强制转换为数值”相同。

除了加法运算符有可能把运算子转为字符串,其他运算符都会把两侧的运算子自动转成数值。


'5' - '2' // 3
'5' * '2' // 10
true - 1  // 0
false - 1 // -1
'1' - 1   // 0
'5'*[]    // 0
false/'5' // 0
'abc'-1   // NaN

上面都是二元算术运算符的例子,JavaScript的两个一元算术运算符——正号和负号——也会把运算子自动转为数值。


+'abc' // NaN
-'abc' // NaN
+true // 1
-false // 0

小结

由于自动转换有很大的不确定性,而且不易除错,建议在预期为布尔值、数值、字符串的地方,全部使用Boolean、Number和String方法进行显式转换。

加法运算符的类型转化

加法运算符(+)需要特别讨论,因为它可以完成两种运算(加法和字符连接),所以不仅涉及到数据类型的转换,还涉及到确定运算类型。

三种情况

加法运算符的类型转换,可以分成三种情况讨论。

(1)运算子之中存在字符串

两个运算子之中,只要有一个是字符串,则另一个不管是什么类型,都会被自动转为字符串,然后执行字符串连接运算。前面的《自动转换为字符串》一节,已经举了很多例子。

(2)两个运算子都为数值或布尔值

这种情况下,执行加法运算,布尔值转为数值(true为1,false为0)。


true + 5 // 6

true + true // 2

(3)运算子之中存在对象

运算子之中存在对象(或者准确地说,存在非原始类型的值),则先调用该对象的valueOf方法。如果返回结果为原始类型的值,则运用上面两条规则;否则继续调用该对象的toString方法,对其返回值运用上面两条规则。


1 + [1,2]
// "11,2"

上面代码的运行顺序是,先调用[1,2].valueOf(),结果还是数组[1,2]本身,则继续调用[1,2].toString(),结果字符串“1,2”,所以最终结果为字符串“11,2”。


1 + {a:1}
// "1[object Object]"

对象{a:1}的valueOf方法,返回的就是这个对象的本身,因此接着对它调用toString方法。({a:1}).toString()默认返回字符串"[object Object]",所以最终结果就是字符串“1[object Object]”

有趣的是,如果更换上面代码的运算次序,就会得到不同的值。


{a:1} + 1
// 1

原来此时,JavaScript引擎不将{a:1}视为对象,而是视为一个代码块,这个代码块没有返回值,所以被忽略。因此上面的代码,实际上等同于 {a:1};+1 ,所以最终结果就是1。为了避免这种情况,需要对{a:1}加上括号。


({a:1})+1
"[object Object]1"

将{a:1}放置在括号之中,由于JavaScript引擎预期括号之中是一个值,所以不把它当作代码块处理,而是当作对象处理,所以最终结果为“[object Object]1”。


1 + {valueOf:function(){return 2;}}
// 3

上面代码的valueOf方法返回数值2,所以最终结果为3。


1 + {valueOf:function(){return {};}}
// "1[object Object]"

上面代码的valueOf方法返回一个空对象,则继续调用toString方法,所以最终结果是“1[object Object]”。


1 + {valueOf:function(){return {};}, toString:function(){return 2;}}
// 3

上面代码的toString方法返回数值2(不是字符串),则最终结果就是数值3。


1 + {valueOf:function(){return {};}, toString:function(){return {};}}
// TypeError: Cannot convert object to primitive value

上面代码的toString方法返回一个空对象,JavaScript就会报错,表示无法获得原始类型的值。

四个特殊表达式

有了上面这些例子,我们再进一步来看四个特殊表达式。

(1)空数组 + 空数组


[] + []
// ""

首先,对空数组调用valueOf方法,返回的是数组本身;因此再对空数组调用toString方法,生成空字符串;所以,最终结果就是空字符串。

(2)空数组 + 空对象


[] + {}
// "[object Object]"

这等同于空字符串与字符串“[object Object]”相加。因此,结果就是“[object Object]”。

(3)空对象 + 空数组


{} + []
// 0

JavaScript引擎将空对象视为一个空的代码块,加以忽略。因此,整个表达式就变成“+ []”,等于对空数组求正值,因此结果就是0。转化过程如下:


+ []
// Number([])
// Number([].toString())
// Number("")
// 0

如果JavaScript不把前面的空对象视为代码块,则结果为字符串“[object Object]”。


({}) + []
// "[object Object]"

(4)空对象 + 空对象


{} + {}
// NaN

JavaScript同样将第一个空对象视为一个空代码块,整个表达式就变成“+
{}”。这时,后一个空对象的ValueOf方法得到本身,再调用toSting方法,得到字符串“[object
Object]”,然后再将这个字符串转成数值,得到NaN。所以,最后的结果就是NaN。转化过程如下:


+ {}
// Number({})
// Number({}.toString())
// Number("[object Object]")

如果,第一个空对象不被JavaScript视为空代码块,就会得到“[object Object][object Object]”的结果。


({}) + {}
// "[object Object][object Object]"

({} + {})
// "[object Object][object Object]" 

console.log({} + {})
// "[object Object][object Object]"

var a = {} + {};
a
// "[object Object][object Object]"

需要指出的是,对于第三和第四种情况,Node.js的运行结果不同于浏览器环境。


{} + {}
// "[object Object][object Object]"

{} + []
// "[object Object]"

可以看到,Node.js没有把第一个空对象视为代码块。原因是Node.js的命令行环境,内部执行机制大概是下面的样子:


eval.call(this,"(function(){return {} + {}}).call(this)")

Node.js把命令行输入都放在eval中执行,所以不会把起首的大括号理解为空代码块加以忽略。

时间: 2024-10-03 21:42:37

js笔记——js数据类型转换的相关文章

js笔记——js里var与变量提升

var是否可以省略 一般情况下,是可以省略var的,但有两点值得注意: 1.var a=1 与 a=1 ,这两条语句一般情况下作用是一样的.但是前者不能用delete删除.不过,绝大多数情况下,这种差异是可以忽略的. 2.在函数内部,如果没有用var 进行申明,则创建的变量是全局变量,而不是局部变量了. 所以,建议变量申明加上var关键字. 变量提升 JavaScript引擎的工作方式是,先解析代码,获取所有被声明的变量,然后再一行一行地运行.这造成的结果,就是所有的变量的声明语句,都会被提升到

js笔记——js里的null和undefined

以下内容摘录自阮一峰的<语法概述 -- JavaScript 标准参考教程(alpha)>章节『5.null和undefined』,以做备忘. null与undefined都可以表示"没有",含义非常相似.目前null和undefined基本是同义的,只有一些细微的差别. 在if语句中,它们都会被自动转为false,null == undefined返回true. 对于null和undefined,可以大致可以像下面这样理解. null表示空值,即该处的值现在为空.典型用法

javascript中数据类型转换详解

在js中,数据类型转换分为显式数据类型转换和隐式数据类型转换. 1, 显式数据类型转换 a:转数字: 1)Number转换: 代码: vara = "123";   a = Number(a); 注意: a) 如果转换的内容本身就是一个数值类型的字符串,那么将来在转换的时候会返回自己. b) 如果转换的内容本身不是一个数值类型的字符串,那么在转换的时候结果是NaN. c) 如果要转换的内容是空的字符串,那以转换的结果是0. d) 如果是其它的字符,那么将来在转换的时候结果是NaN. 2

js 数据类型转换总结笔记_javascript技巧

javascript有如下数据类型的转换方法: 一,转换成数字 xxx*1.0 转换成字符串 xxx+"" 二,从一个值中提取另一种类型的值,并完成转换工作. .提取字符串中的整数:parseInt(); 例:parseInt("123zhang")的结果为123 .提取字符串中的浮点数:parseFloat(); 例:parseFloat("0.55zhang")的结果为0.55 .执行用字符串表示的一段javascript代码:eval();

Js中常用的数据类型转换示例详解

在编写js代码的时候,经常会用到数据类型转换,必须获取到的div高度,默认后面带有单位,那么如何把这个单位去掉,将字符串转换为整数类型的变量呢,今天我们就来谈谈javascript数据类型转换的方法总结. 在javascript中数据类型转换有三种方法:转换函数.强制类型转换.利用js变量弱类型转换. 转换函数 js提供了parseInt()和parseFloat()两个转换函数.前者把值转换成整数,后者把值转换成浮点数.只有对String类型调用这些方法,这两个函数才能正确运行:对其他类型返回

浅谈JS中json数据的处理_javascript技巧

1. json数据结构(对象和数组) json对象:var obj = {"name":"xiao","age":12}; json数组:var objArray = [{"name":"xiao","age":12},{"name":"xiao","age":12}]; 2. 处理json数据,依赖文件有:jQuery.js

JS中Json数据的处理和解析JSON数据的方法详解_javascript技巧

JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式.它基于ECMAScript的一个子集. JSON采用完全独立于语言的文本格式,但是也使用了类似于C语言家族的习惯(包括C.C++.C#.Java.JavaScript.Perl.Python等).这些特性使JSON成为理想的数据交换语言. 易于人阅读和编写,同时也易于机器解析和生成(一般用于提升网络传输速率). JSON的规则很简单: 对象是一个无序的"'名称/值'对"集合.一个对象以&quo

ext/js-Ext/js主从表数据在一个界面展示的问题

问题描述 Ext/js主从表数据在一个界面展示的问题 类似于一个订单列表,每行后面有一个查看详情的按钮,现在是点击查看详情,展示了主表数据,怎么样才能在点击查看详情的时候,除了展示当前订单记录行的信息,还要展示这一条订单关联的多条订单明细信息呢?在一个界面,跟在订单信息后面展示? 解决方案 可以用Ext.ux.RowExpander这个插件,具体示例看examplesgridgrid-plugins.html

探讨JS表现与数据分离

首先,当时我简历是抄的,里面有一句"对表现与数据分离有一定理解",然后面试官就针对这点开问了 PS:尼玛,那是抄的,我哪里知道他是干神马的...... 为了帮助我展开思维,面试官出了一道题: 他有一个国家列表,现在要将国家列表放到A中,然后B可以由A选择,也可以有总列表选择 但是B中添加后,若是A中没有要动态为A增加这项. 问题出来了,我现在一看就知道面试官想问什么了......当时其实没有理解到啦...... 现在来看,说这道题与表现与数据分离有关是没有问题的,却不一定让人很好的产生