JavaScript隐式类型转换


Posted in Javascript onMarch 15, 2016

JavaScript的数据类型是非常弱的(不然不会叫它做弱类型语言了)!在使用算术运算符时,运算符两边的数据类型可以是任意的,比如,一个字符串可以和数字相加。之所以不同的数据类型之间可以做运算,是因为JavaScript引擎在运算之前会悄悄的把他们进行了隐式类型转换的,如下是数值类型和布尔类型的相加:

3 + true; // 4

结果是一个数值型!如果是在C或者Java环境的话,上面的运算肯定会因为运算符两边的数据类型不一致而导致报错的!但是,在JavaScript中,只有少数情况下,错误类型才会导致出错,比如调用非函数,或者读取null或者undefined的属性时,如下:

"hello"(1); // error: not a function

null.x; // error: cannot read property 'x' of null

多数情况下,JavaScript都不会出错的,而是自动的进行相应的类型转换。比如-, *, /,和%等算术运算符都会把操作数转换成数字的,但是“+”号就有点不一样了,有些情况下,它是算术加号,有些情况下,是字符串连接符号,具体的要看它的操作数,如下:

2 + 3; // 5

"hello" + " world"; // "hello world"

但是,如果字符串和数字相加,会是怎样的结果呢?JavaScript会自动把数字转换成字符的,不管数字在前还是字符串在前,如下:

"2" + 3; // "23"

2 + "3"; // "23"

字符串和数字相加结果是字符串,字符串和数字相加结果是字符串,字符串和数字相加结果是字符串,重要的事情说三遍!!!!!!

此外,需要注意的是,“+”的运算方向是从左到右的,如下:

1 + 2 + "3"; // "33"

这与下面是等价的:

(1 + 2) + "3"; // "33"

相比之下,下面的结果是不一样的:

1 + "2" + 3; // "123"

但是,隐式类型转换,有时候,会隐藏一些错误的,比如,null会转换成0,undefined会转换成NaN。需要注意的是,NaN和NaN是不相等的(这是由于浮点数的精度决定的),如下:

var x = NaN;

x === NaN; // false

虽然,JavaScript提供了isNaN来检测某个值是否为NaN,但是,这也不太精确的,因为,在调用isNaN函数之前,本身就存在了一个隐式转换的过程,它会把那些原本不是NaN的值转换成NaN的,如下:

isNaN("foo"); // true

isNaN(undefined); // true

isNaN({}); // true

isNaN({ valueOf: "foo" }); // true

上面代码,我们使用isNaN来测试后,发现字符串,undefined,甚至对象,结果都返回真!!!但是,我们总不能说他们也是NaN吧?总而言之,得出的结论是:isNaN检测NaN并不可靠!!!

幸运的是,有一种可靠的并且准确的方法可以检测NaN。我们都知道,只有NaN是自己不等自己的,那么,我们就以使用不等于号(!==)来判断一个数是否等于自身,从而,可以检测到NaN了,如下:

var a = NaN;
a !== a; // true
var b = "foo";
b !== b; // false
var c = undefined;
c !== c; // false
var d = {};
d !== d; // false
var e = { valueOf: "foo" };
e !== e; // false

我们也可以把这种模式定义成一个函数,如下:

function isReallyNaN(x) {
return x !== x;
}

OK,NaN的检测方法就是这么简单,我们下面继续讨论对象的隐式转换!

对象是可以转换成原始值的,最常见的方法就是把它转换成字符串,如下:

"the Math object: " + Math; // "the Math object: [object Math]"
"the JSON object: " + JSON; // "the JSON object: [object JSON]"

对象转换成字符串是调用了他的toSting函数的,你可以手动的调用它来检测一下:

Math.toString(); // "[object Math]"
JSON.toString(); // "[object JSON]"

类似的,对象也是可以转换成数字的,他是通过valueOf函数的,当然,你也是可以自定义这个valueOf函数的,如下:

"J" + { toString: function() { return "S"; } }; // "JS"
2 * { valueOf: function() { return 3; } }; // 6

如果,一个对象同时存在valueOf方法和toString方法,那么,valueOf方法总是会被优先调用的,如下:

var obj = {
toString: function() {
return "[object MyObject]";
},
valueOf: function() {
return 17;
}
};
"object: " + obj; // "object: 17"

但是,多数情况下,这都不是我们想要的,一般的,尽可能使valueOf和toString表示的值相同(尽管类型可以不同)。

最后一种强制类型转换,我们常常称之为“真值运算”,比如,if, ||, &&,他们的操作数不一定是布尔型的额。JavaScript会通过简单的转换规则,将一些非布尔类型的值转换成布尔型的。大多数的值都会转换成true,只有少数的是false,他们分别是:false, 0, -0, ”", NaN, null, undefined,因为存在数字和字符串以及对象的值为false,所以,直接用真值转换来判断一个函数的参数是否传进来了,这是不不太安全的。比如,有一个可以具有默认值得可选参数的函数,如下:

function point(x, y) {
if (!x) {
x = 320;
}
if (!y) {
y = 240;
}
return { x: x, y: y };
}

这个函数会忽略任何的真值为假的参数的,包括0,-0;

point(0, 0); // { x: 320, y: 240 }

检测undefined的更加准确的方法是用typeof操作:

function point(x, y) {
if (typeof x === "undefined") {
x = 320;
}
if (typeof y === "undefined") {
y = 240;
}
return { x: x, y: y };
}

这种写法,可以区分开0和undefined的:

point(); // { x: 320, y: 240 }
point(0, 0); // { x: 0, y: 0 }

另外一种方法是利用参数跟undefined作比较,如下:

if (x === undefined) { ... }

总结:

1. 类型错误有可能会被类型转换所隐藏。

2. “+”既可以表示字符串连接,又可以表示算术加,这取决于它的操作数,如果有一个为字符串的,那么,就是字符串连接了。

3. 对象通过valueOf方法,把自己转换成数字,通过toString方法,把自己转换成字符串。

4.具有valueOf方法的对象,应该定义一个相应的toString方法,用来返回相等的数字的字符串形式。

5.检测一些未定义的变量时,应该使用typeOf或者与undefined作比较,而不应该直接用真值运算。

关于JavaScript隐式类型转换就给大家介绍到这里,希望对大家有所帮助!

Javascript 相关文章推荐
jquery 弹出登录窗口实现代码
Dec 24 Javascript
angularjs客户端实现压缩图片文件并上传实例
Jul 06 Javascript
如何动态加载外部Javascript文件
Dec 02 Javascript
利用JavaScript阻止表单提交的两种方法
Aug 11 Javascript
JavaScript 随机验证码的生成实例代码
Sep 22 Javascript
js css3实现图片拖拽效果
Mar 04 Javascript
在页面中引入js的两种方法(推荐)
Aug 29 Javascript
在Vue中使用highCharts绘制3d饼图的方法
Feb 08 Javascript
一个基于react的图片裁剪组件示例
Apr 18 Javascript
微信小程序自定义组件之可清除的input组件
Jul 17 Javascript
vue深度监听(监听对象和数组的改变)与立即执行监听实例
Sep 04 Javascript
vue使用svg文件补充-svg放大缩小操作(使用d3.js)
Sep 22 Javascript
JavaScript正则表达式匹配 div  style标签
Mar 15 #Javascript
Angularjs整合微信UI(weui)
Mar 15 #Javascript
一步步教大家编写酷炫的导航栏js+css实现
Mar 14 #Javascript
原生javascript+css3编写的3D魔方动画旋扭特效
Mar 14 #Javascript
基于javascript html5实现3D翻书特效
Mar 14 #Javascript
php基于redis处理session的方法
Mar 14 #Javascript
使用javascript插入样式
Mar 14 #Javascript
You might like
PHP5中的this,self和parent关键字详解教程
2007/03/19 PHP
php递归获取目录内文件(包含子目录)封装类分享
2013/12/25 PHP
php自定义函数截取汉字长度
2014/05/15 PHP
关于PHP 如何用 curl 读取 HTTP chunked 数据
2016/02/26 PHP
PHP实现对xml的增删改查操作案例分析
2017/05/19 PHP
php实现的顺序线性表示例
2019/05/04 PHP
juqery 学习之三 选择器 子元素与表单
2010/11/25 Javascript
jQuery下的动画处理总结
2013/10/10 Javascript
javascript匿名函数应用示例介绍
2014/03/07 Javascript
js 获取时间间隔实现代码
2014/05/12 Javascript
jquery实现的一个文章自定义分段显示功能
2014/05/23 Javascript
jQuery实现简单的图片查看器
2020/09/11 Javascript
利用jQuery插件imgAreaSelect实现图片上传裁剪(放大缩小)
2016/12/02 Javascript
15个非常实用的JavaScript代码片段
2016/12/18 Javascript
bootstrap-table.js扩展分页工具栏(增加跳转到xx页)功能
2017/12/28 Javascript
vue-cli3.0使用及部分配置详解
2018/08/29 Javascript
原生JS实现自定义下拉单选选择框功能
2018/10/12 Javascript
简述vue路由打开一个新的窗口的方法
2018/11/29 Javascript
使用Three.js实现太阳系八大行星的自转公转示例代码
2019/04/09 Javascript
浅谈 Webpack 如何处理图片(开发、打包、优化)
2019/05/15 Javascript
layui添加动态菜单与选项卡 AJAX请求的例子
2019/09/25 Javascript
vue中axios防止多次触发终止多次请求的示例代码(防抖)
2020/02/16 Javascript
javascript将16进制的字符串转换为10进制整数hex
2020/03/05 Javascript
[02:49]DAC2018决赛日TOP5 LGD开启黑暗之门绝杀VP
2018/04/08 DOTA
洛杉矶时尚女装系列:J.ING US
2019/03/17 全球购物
日本航空官方网站:JAL
2019/06/19 全球购物
俄罗斯小米家用电器、电子产品和智能家居商店:Poood.ru
2020/04/03 全球购物
个人安全承诺书
2014/05/22 职场文书
技术股份合作协议书
2014/10/05 职场文书
2014年维修电工工作总结
2014/11/20 职场文书
致地震灾区的慰问信
2015/03/23 职场文书
检讨书怎么写
2015/05/07 职场文书
聘任协议书(挂靠)
2015/09/21 职场文书
2016年先进班集体事迹材料
2016/02/26 职场文书
七年级作文之秋游
2019/10/21 职场文书
nginx对http请求处理的各个阶段详析
2021/03/31 Servers