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

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
强制转换
,以便于您获取更多的相关知识。

时间: 2024-08-02 23:21:44

跟我学习javascript的隐式强制转换_javascript技巧的相关文章

Javascript var变量隐式声明方法_javascript技巧

诸如此类.这有一个问题,比如说在代码中的某一行,我想使用的一个已声明的变量x,结果由于打字或者拼写错误,这个变量被写成y了,结果相当于"隐式"声明了一个变量y,在实际编程过程中,这种错误有时比较难以发现. 除此之外,今天通过同事介绍,了解到这种"隐式声明"中的别外一个问题. 当你在当前上下文内进行这种"隐式"声明时,JavaScript引擎会先在当前上下文中寻找是否之前有声明此变量,如果没有,再到上一级的上下文中去寻找,如果一直未找到,会最后在w

学习JavaScript设计模式之装饰者模式_javascript技巧

有时我们不希望某个类天生就非常庞大,一次性包含许多职责.那么我们就可以使用装饰着模式. 装饰着模式可以动态地给某个对象添加一些额外的职责,从而不影响这个类中派生的其他对象. 装饰着模式将一个对象嵌入另一个对象之中,实际上相当于这个对象被另一个对象包装起来,形成一条包装链. 一.不改动原函数的情况下,给该函数添加些额外的功能 1. 保存原引用 window.onload = function() { console.log(1); }; var _onload = window.onload ||

20条学习javascript的编程规范的建议_javascript技巧

1.使用js文件管理代码 所有代码尽量放在js文件中,然后再html文件中使用script引入,引入时注意放在body标签后面,并且不使用type或者language. 2.书写缩进 使用4个空白格缩进,注意不要使用tab键进行缩进. 3.断句 注意行长,每行不超过80个字符,超过时要进行适当断句,断句应该再操作符后面进行,最理想的是在逗号(,)后面进行断句,断句后下一行使用8格缩进. 4.注解 一般使用单行注释,块注释一般用于文档. 5.变量声明 所有变量使用之前先声明,未声明的变量会自动作为

学习javascript面向对象 实例讲解面向对象选项卡_javascript技巧

本文实例讲解了最简单的面向对象选项卡实现方法,分享给大家供大家参考,具体内容如下 效果图: 1.功能说明 点击三个按钮分别显示对应的选项卡 2.html代码说明 <div class="box" id="box"> <ul class="list"> <li class="in_active">第一张选项卡</li> <li class="in">

跟我学习javascript的函数和函数表达式_javascript技巧

1.函数声明与函数表达式 在ECMAScript中,创建函数的最常用的两个方法是函数表达式和函数声明,两者期间的区别是有点晕,因为ECMA规范只明确了一点:函数声明必须带有标示符(Identifier)(就是大家常说的函数名称),而函数表达式则可以省略这个标示符: 函数声明:function 函数名称 (参数:可选){ 函数体 } 函数表达式:function 函数名称(可选)(参数:可选){ 函数体 } 所以,可以看出,如果不声明函数名称,它肯定是表达式,可如果声明了函数名称的话,如何判断是函

学习JavaScript设计模式之责任链模式_javascript技巧

一.定义 责任链模式:使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系,将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止. 二.示例 假设这么一个场景: 我们负责一个售卖手机的电商网站,经过分别缴纳500元定金和200元定金的两轮预定后,到了正式购买阶段.针对预定用户实行优惠,支付过500元定金的用户会收到100元的商城优惠券,支付过200元定金的用户会收到50元的商城优惠券,没有支付定金的用户归为普通购买,且在库存有限的情况下不一定保证买到. /*

学习Javascript闭包(Closure)知识_javascript技巧

一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域无非就是两种:全局变量和局部变量. Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量. var n=999; function f1(){ alert(n); } f1(); // 999 另一方面,在函数外部自然无法读取函数内的局部变量. function f1(){ var n=999; } alert(n); // error 这里有一个地方需要注意,函数内部声明变量的时候,

跟我学习javascript的异步脚本加载_javascript技巧

先来看这行代码: <script src = "allMyClientSideCode.js"></script> 这有点儿--不怎么样."这该放在哪儿?"开发人员会奇怪,"靠上点,放到<head>标签里?还是靠下点,放到<body>标签里?"这两种做法都会让富脚本站点的下场很凄惨.<head>标签里的大脚本会滞压所有页面渲染工作,使得用户在脚本加载完毕之前一直处于"白屏死机&

跟我学习javascript解决异步编程异常方案_javascript技巧

一.JavaScript异步编程的两个核心难点 异步I/O.事件驱动使得单线程的JavaScript得以在不阻塞UI的情况下执行网络.文件访问功能,且使之在后端实现了较高的性能.然而异步风格也引来了一些麻烦,其中比较核心的问题是: 1.函数嵌套过深 JavaScript的异步调用基于回调函数,当多个异步事务多级依赖时,回调函数会形成多级的嵌套,代码变成 金字塔型结构.这不仅使得代码变难看难懂,更使得调试.重构的过程充满风险. 2.异常处理 回调嵌套不仅仅是使代码变得杂乱,也使得错误处理更复杂.这