有趣的JavaScript隐式类型转换操作实例分析


Posted in Javascript onMay 02, 2020

本文实例讲述了JavaScript隐式类型转换操作。分享给大家供大家参考,具体如下:

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作比较,而不应该直接用真值运算。

感兴趣的朋友可以使用在线HTML/CSS/JavaScript代码运行工具:http://tools.3water.com/code/HtmlJsRun测试上述代码运行效果。

希望本文所述对大家JavaScript程序设计有所帮助。

Javascript 相关文章推荐
JavaScript constructor和instanceof,JSOO中的一对欢喜冤家
May 25 Javascript
基于jQuery实现的当离开页面时出现提示的实现代码
Jun 27 Javascript
有关于eclipse配置spket需要注意的一些地方
Apr 07 Javascript
jquery实现漂浮在网页右侧的qq在线客服插件示例
May 13 Javascript
Javascript 修改String 对象 增加去除空格功能(示例代码)
Nov 30 Javascript
纯js写的分页表格数据为json串
Feb 18 Javascript
JS实现单击输入框弹出选择框效果完整实例
Dec 14 Javascript
jQuery如何解决IE输入框不能输入的问题
Oct 08 Javascript
js 定位到某个锚点的方法
Nov 19 Javascript
概述jQuery的元素筛选
Nov 23 Javascript
vue2.0页面前进刷新回退不刷新的实现方法
Jul 31 Javascript
命令行批量截图Node脚本示例代码
Jan 25 Javascript
react-router-dom 嵌套路由的实现
May 02 #Javascript
在react中使用vue的状态管理的方法示例
May 02 #Javascript
JS表单验证插件之数据与逻辑分离操作实例分析【策略模式】
May 01 #Javascript
javascript实现的图片预览和上传功能示例【兼容IE 9】
May 01 #Javascript
jQuery实现的移动端图片缩放功能组件示例
May 01 #jQuery
jQuery实现移动端图片上传预览组件的方法分析
May 01 #jQuery
jQuery实现的上拉刷新功能组件示例
May 01 #jQuery
You might like
Http 1.1 Etag 与 Last-Modified提高php效率
2008/01/10 PHP
在PHP中使用curl_init函数的说明
2010/11/02 PHP
PHP删除数组中的特定元素的代码
2012/06/28 PHP
php绘制一个矩形的方法
2015/01/24 PHP
PHP用mb_string函数库处理与windows相关中文字符及Win环境下开启PHP Mb_String方法
2015/11/11 PHP
PHP实现发送邮件的方法(基于简单邮件发送类)
2015/12/17 PHP
PHP与JavaScript针对Cookie的读写、交互操作方法详解
2017/08/07 PHP
jQuery 解析xml文件
2009/08/09 Javascript
javascript与CSS复习(《精通javascript》)
2010/06/29 Javascript
jQuery Ajax请求状态管理器打包
2012/05/03 Javascript
一个JS的日期格式化算法示例
2013/07/31 Javascript
JavaScript节点及列表操作实例小结
2015/08/05 Javascript
jQuery实现的个性化返回底部与返回顶部特效代码
2015/10/30 Javascript
封装获取dom元素的简单实例
2016/07/08 Javascript
Three.js快速入门教程
2016/09/09 Javascript
微信小程序实现顶部选项卡(swiper)
2020/06/19 Javascript
利用nginx + node在阿里云部署https的步骤详解
2017/12/19 Javascript
jQuery NProgress.js加载进度插件的简单使用方法
2018/01/31 jQuery
vue中element-ui表格缩略图悬浮放大功能的实例代码
2018/06/26 Javascript
layer实现登录弹框,登录成功后关闭弹框并调用父窗口的例子
2019/09/11 Javascript
[01:59]翻天覆地,因你而变,7.20版本地图更新速览
2018/11/24 DOTA
对dataframe数据之间求补集的实例详解
2019/01/30 Python
香港时装购物网站:ZALORA香港
2017/04/23 全球购物
阿迪达斯墨西哥官方网站:adidas墨西哥
2017/11/03 全球购物
如何在Shell脚本中使用函数
2015/09/06 面试题
舞蹈教育学专业推荐信
2013/11/27 职场文书
《天游峰的扫路人》教学反思
2014/04/25 职场文书
护士找工作求职信
2014/07/02 职场文书
教师演讲稿开场白
2014/08/25 职场文书
教师节慰问信
2015/02/15 职场文书
《称赞》教学反思
2016/02/17 职场文书
2019班干部竞选演讲稿范本!
2019/07/08 职场文书
导游词之西安骊山
2019/12/03 职场文书
教你怎么用python爬取爱奇艺热门电影
2021/05/20 Python
Python趣味挑战之实现简易版音乐播放器
2021/05/28 Python
nginx location 带斜杠【 / 】与不带的区别
2022/04/13 Servers