跟我学习javascript的隐式强制转换


Posted in Javascript onNovember 16, 2015

JavaScript的数据类型分为六种,分别为null,undefined,boolean,string,number,object。

object是引用类型,其它的五种是基本类型或者是原始类型。我们可以用typeof方法打印来某个是属于哪个类型的。不同类型的变量比较要先转类型,叫做类型转换,类型转换也叫隐式转换。隐式转换通常发生在运算符加减乘除,等于,还有小于,大于等。。

typeof '11' //string 
typeof(11)  //number
'11' < 4 //false

一、基本类型的转换

下面先讲加减乘除:

1. 字符串加数字,数字就会转成字符串。

2. 数字减字符串,字符串转成数字如果字符串不是纯数字就会转成NaN。字符串减数字也一样。两个字符串相减也先转成数字。

3. 乘,除,大于,小于跟减的转换也是一样。

//隐式转换 + - * == / 
// + 
10 + '20' //'2010'
// -
10 - '20' //-10
10 - 'one' //NaN
10 - '100a' //NaN
// *
10*'20' //200
'10'*'20' //200
// /
20/'10' //2
'20'/'10' //2
'20'/'one'  //NaN

4.加法操作顺序是敏感的

类似这样的混合表达式有时令人困惑,因为 JavaScript 对操作顺序是敏感的。例如,表达式:1+2+"3";  //"33"

由于加法运算是自左结合的(即左结合律),因此,它等同于下面的表达式:(1+2)+"3";  //"33"

与此相反,表达式:1+"2"+3;  //"123"的计算结果为字符串“123”。左结合律相当于是将表达式左侧的加法运算包裹在括号中。

5.再来看看一组 ==

1).undefined等于null

2).字符串和数字比较时,字符串转数字

3).数字为布尔比较时,布尔转数字

4).字符串和布尔比较时,两者转数字

// ==
undefined == null; //true
'0' == 0;  //true,字符串转数字
0 == false; //true,布尔转数字
'0' == false; 
 //true,两者转数字
null == false;   //false
undefined == false;  //false

7个false值:false,0,-0,“”,NaN,null以及undefined,所有其他值都是truth

6、NaN,不是一个数字

NaN 是一个特殊值,说明某些算术运算(如求负数的平方根)的结果不是数字。方法 parseInt() 和 parseFloat() 在不能解析指定的字符串时就返回这个值。对于一些常规情况下返回有效数字的函数,也可以采用这种方法,用 Number.NaN 说明它的错误情况。

Math.sqrt(-2)
Math.log(-1)
0/0
parseFloat('foo')

对于很多JavaScript的初学者来说,它的第一个陷阱是调用typeof时返回结果的通常是你想不到的:

console.log(typeof NaN); // 'Number'

这情情况下,NaN并不意味着是一个数字,它的类型是数字。明白吗?
因为typeof 返回的是字符串,有六种:“number”、”string”、”boolean”、”object”、”function”、”undefined

保持冷静,因为下面还有很多混乱的地方。让我们比较两个NaN:

var x = Math.sqrt(-2);
var y = Math.log(-1);
console.log(x == y); // false

也许这是因为我们没有使用严格等价(===)操作?显然不是。

var x = Math.sqrt(-2);
var y = Math.log(-1);
console.log(x === y); // false

直接比较两个NaN呢?

console.log(NaN === NaN); // false

因为有很多方法来表示一个非数字,所以一个非数字不会等于另一个为NaN的非数字,它还是有一定道理的。

但是当然,解决方案现在已经有了。让我们认识一下全局函数isNaN:

console.log(isNaN(NaN)); // true

唉,不过 isNaN() 也有它自己的很多缺陷呀:

console.log(isNaN('hello')); // true
console.log(isNaN(['x'])); // true
console.log(isNaN({})); // true

这样又产生了很多不同的解决方案。其中一个是利用 了NaN的非反射性质(例如, 看看 Kit Cambridge 的笔记)

var My = {
 isNaN: function (x) { return x !== x; }
}

不过幸运的是,在即将到来的ECMAScript 6中, 有一个Number.isNaN() 方法提供可靠的NaN值检测。
换句话说,只有在参数是真正的NaN时,才会返回true

console.log(Number.isNaN(NaN)); // true
console.log(Number.isNaN(Math.sqrt(-2))); // true
console.log(Number.isNaN('hello')); // false
console.log(Number.isNaN(['x'])); // false
console.log(Number.isNaN({})); // false

二、引用类型的转换

基本类型间的比较相对简单。引用类型和基本类型的比较就相对复杂一些,先要把引用类型转成基本类型,再按上述的方法比较。

1.引用类型转布尔全是true。

比如空数组,只要是对象就是引用类型,所以[]为true。引用类型转数字或者字符串就要用valueOf()或者toString();对象本身就继承了valuOf()和toString(),还可以自定义valueOf()和toString()。根据不同的对象用继承的valueOf()转成字符串,数字或本身,而对象用toString就一定转为字符串。一般对象默认调用valueOf()。

1).对象转数字时,调用valueOf();

2).对象转字符串时,调用toString();

先看看下面的例子:

0 == []; // true, 0 == [].valueOf(); ---> 0 == 0;
'0' == []; // false, '0' == [].toString(); ---> '0' == '';
2 == ['2']; // true, 2 == ['2'].valueOf(); ---> 2 == '2' ---> 2 == 2;
'2' == [2]; // true, '2' == [2].toString(); ---> '2' =='2';

[] == ![]; //true, [].valueOf() == !Boolean([]) -> 0 == false ---> 0 == 0;

对象转成数字时,调用valueOf(),在这之前先调用的是toString();所以我猜valueOf方法是这样的。So上面的例子 0 == []要改成下面更合理。无论如何,[]最后是转成0的。

var valueOf = function (){
 var str = this.toString(); //先调用toString(),转成字符串
 //...
}
0 == []; // true, 0 == [].valueOf(); -> 0 == '0' -> 0 == 0;

自定义的valueOf()和toString();

  • 自定义的valueOf()和toString()都存在,会默认调用valueOf();
  • 如果只有toString(),则调用toString();
var a = [1];

a.valueOf = function (){ return 1;}
a.toString = function (){ return '1';}

a + 1; // 2, valueOf()先调用

去掉valueOf()就会调用toString()。

var a = [1];

a.valueOf = function (){ return 1;}
a.toString = function (){ return '1';}

a + 1; // 2, 先调用valueOf()
//去掉valueOf
delete a.valueOf;
a + 1; // '11', 调用toString()

如果返回其它会怎么样呢?

var a = [1];

a.valueOf = function (){return ;}
a.toString = function (){return 1 ;};

1 - a; //NaN

其它对象 调用valueOf()转成不同的类型:

var a = {};
a.valueOf(); //Object {}
var a = [];
a.valueOf(); //[] 自己本身
var a = new Date();
a.valueOf(); //1423812036234 数字
var a = new RegExp();
a.valueOf(); // /(?:)/ 正则对象

引用类型之间的比较是内存地址的比较,不需要进行隐式转换,这里不多说。

[] == [] //false 地址不一样

var a = [];
b = a;
b == a //true

2.显式转换

显式转换比较简单,可以直接用类当作方法直接转换。

Number([]); //0
String([]); //”
Boolean([]); //true

还有更简单的转换方法。

3 + ” // 字符串'3'
+'3' // 数字3
!!'3' // true

以上就是本文的全部内容,详细介绍了javascript的隐式强制转换,希望对大家的学习有所帮助。

Javascript 相关文章推荐
JavaScript 数组运用实现代码
Apr 13 Javascript
javascript实现删除前弹出确认框
Jun 04 Javascript
理解Javascript文件动态加载
Jan 29 Javascript
jquery 全选、全不选、反选效果的实现代码【推荐】
May 05 Javascript
AngularJS实现在ng-Options加上index的解决方法
Nov 03 Javascript
JS SetInterval 代码实现页面轮询
Aug 11 Javascript
jquery select插件异步实时搜索实例代码
Oct 20 jQuery
JS中使用new Option()实现时间联动效果
Dec 10 Javascript
layui 监听select选择 获取当前select的ID名称方法
Sep 24 Javascript
js new Date()实例测试
Oct 31 Javascript
JavaScript实现像雪花一样的Hexaflake分形
Jul 07 Javascript
vue elementUI表格控制对应列
Apr 13 Vue.js
跟我学习javascript的浮点数精度
Nov 16 #Javascript
跟我学习javascript的严格模式
Nov 16 #Javascript
javascript中tostring()和valueof()的用法及两者的区别
Nov 16 #Javascript
关于javascript中dataset的问题小结
Nov 16 #Javascript
javascript入门教程基础篇
Nov 16 #Javascript
JavaScript中函数表达式和函数声明及函数声明与函数表达式的不同
Nov 15 #Javascript
浅谈JavaScript中的对象及Promise对象的实现
Nov 15 #Javascript
You might like
PHP 基本语法格式
2009/12/15 PHP
thinkphp实现数组分页示例
2014/04/13 PHP
PHP代码维护,重构变困难的4种原因分析
2016/01/25 PHP
php正则表达式验证(邮件地址、Url地址、电话号码、邮政编码)
2016/03/14 PHP
PHP模板引擎Smarty内置变量调解器用法详解
2016/04/11 PHP
Laravel统一错误处理为JSON的方法介绍
2020/10/18 PHP
Gird组件 Part-3:范例RSSFeed Viewer
2007/03/10 Javascript
jQuery $.each的用法说明
2010/03/22 Javascript
jQuery满意度星级评价插件特效代码分享
2015/08/19 Javascript
javascript prototype原型详解(比较基础)
2016/12/26 Javascript
JS中showModalDialog关闭子窗口刷新主窗口用法详解
2017/03/25 Javascript
node.js express中app.param的用法详解
2017/07/16 Javascript
详解vue 路由跳转四种方式 (带参数)
2019/04/28 Javascript
Vue 使用beforeEach实现登录状态检查功能
2019/10/31 Javascript
AngularJS动态生成select下拉框的方法实例
2019/11/17 Javascript
Vue基于iview实现登录密码的显示与隐藏功能
2020/03/06 Javascript
微信公众号中的JSSDK接入及invalid signature等常见错误问题分析(全面解析)
2020/04/11 Javascript
vue中封装axios并实现api接口的统一管理
2020/12/25 Vue.js
[48:21]林俊杰圣堂刺客超神杀戮秀
2014/10/29 DOTA
举例讲解Python中的迭代器、生成器与列表解析用法
2016/03/20 Python
Django中使用celery完成异步任务的示例代码
2018/01/23 Python
TensorFlow变量管理详解
2018/03/10 Python
使用TensorFlow实现SVM
2018/09/06 Python
python迭代器常见用法实例分析
2019/11/22 Python
python中threading开启关闭线程操作
2020/05/02 Python
解决django 向mysql中写入中文字符出错的问题
2020/05/18 Python
使用Pytorch搭建模型的步骤
2020/11/16 Python
编译 pycaffe时报错:fatal error: numpy/arrayobject.h没有那个文件或目录
2020/11/29 Python
Charlotte Tilbury澳大利亚官网:英国美妆品牌
2018/10/05 全球购物
美国沙龙美发产品购物网站:Hair.com by L’Oreal
2020/11/09 全球购物
优秀小学生家长评语
2014/01/30 职场文书
法人代表任命书范本
2014/06/05 职场文书
健康状况证明书
2014/11/26 职场文书
JavaGUI模仿QQ聊天功能完整版
2021/07/04 Java/Android
spring cloud 配置中心客户端启动遇到的问题
2021/09/25 Java/Android
MySQL外键约束(Foreign Key)案例详解
2022/06/28 MySQL