跟我学习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 相关文章推荐
Jquery下attr和removeAttr的使用方法
Dec 28 Javascript
jQuery.prototype.init选择器构造函数源码思路分析
Feb 05 Javascript
解析window.open的使用方法总结
Jun 19 Javascript
javascript中的Function.prototye.bind
Jun 25 Javascript
js实现图片点击左右轮播
Jul 08 Javascript
js中跨域方法原理详解
Jul 19 Javascript
基于Vue.js实现简单搜索框
Mar 26 Javascript
ES6 Promise对象概念与用法分析
Apr 01 Javascript
浅谈Vue的加载顺序探讨
Oct 25 Javascript
详解VUE-地区选择器(V-Distpicker)组件使用心得
May 07 Javascript
移动端自适应flexible.js的使用方法(不用三大框架,仅写一个单html页面使用)推荐
Apr 02 Javascript
Vue 封装防刷新考试倒计时组件的实现
Jun 05 Javascript
跟我学习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实现像JSP,ASP里Application那样的全局变量
2007/01/12 PHP
PHP 数组遍历方法大全(foreach,list,each)
2010/06/30 PHP
在MongoDB中模拟Auto Increment的php代码
2011/03/06 PHP
php pki加密技术(openssl)详解
2013/07/01 PHP
PHP读取配置文件类实例(可读取ini,yaml,xml等)
2015/07/28 PHP
Laravel jwt 多表(多用户端)验证隔离的实现
2019/12/18 PHP
简单的js表单验证函数
2013/10/28 Javascript
JSF中confirm弹出框的用法示例介绍
2014/01/07 Javascript
js实现的牛顿摆效果
2015/03/31 Javascript
AngularJS 使用$sce控制代码安全检查
2016/01/05 Javascript
基于canvas实现的绚丽圆圈效果完整实例
2016/01/26 Javascript
AngularJS页面访问时出现页面闪烁问题的解决
2016/03/06 Javascript
jQuery实现点击弹出背景变暗遮罩效果实例代码
2016/06/24 Javascript
Vue中的slot使用插槽分发内容的方法
2018/03/01 Javascript
nodejs require js文件入口,在package.json中指定默认入口main方法
2018/10/10 NodeJs
node.JS路径解析之PATH模块使用方法详解
2020/02/06 Javascript
Vue实现PC端靠边悬浮球的代码
2020/05/09 Javascript
[02:28]DOTA2英雄基础教程 狼人
2013/12/23 DOTA
[57:53]DOTA2上海特级锦标赛主赛事日 - 2 败者组第二轮#3OG VS VP
2016/03/03 DOTA
[01:21:58]守擂赛DOTA2第一周决赛
2020/04/22 DOTA
用virtualenv建立多个Python独立虚拟开发环境
2017/07/06 Python
python的scipy实现插值的示例代码
2019/11/12 Python
python 列表、字典和集合的添加和删除操作
2019/12/16 Python
canvas画布实现手写签名效果的示例代码
2019/04/23 HTML / CSS
微软巴西官方网站:Microsoft Brasil
2019/09/26 全球购物
Electric官网:美国高级眼镜和配件品牌
2020/06/04 全球购物
巴西购物网站:Onofre Agora
2020/06/08 全球购物
银行职员思想汇报
2013/12/31 职场文书
企业计划生育责任书
2015/05/09 职场文书
新年晚会主持词开场白
2015/05/28 职场文书
2015年女工委工作总结
2015/07/27 职场文书
Html5页面播放M4a音频文件
2021/03/30 HTML / CSS
Python趣味挑战之给幼儿园弟弟生成1000道算术题
2021/05/28 Python
浅谈Redis位图(Bitmap)及Redis二进制中的问题
2021/07/15 Redis
2021年国产动漫公司排行前十名,玄机科技上榜,第二推出过铠甲勇士
2022/03/18 杂记
postgreSQL数据库基础知识介绍
2022/04/12 PostgreSQL