JavaScript 的数据类型
JavaScript 语言的每一个值,都属于某一种数据类型。JavaScript 的数据类型,共有七种。
一.据类型广义分类
传统分类通过存储位置 把数据类型分为 基本数据类型 和 引用数据类型
基础类型存储在栈内存中 ,引用数据类型存储在堆内存中.
Undefined、Null、Boolean、Number、String和symbol (java的string是引用类型存在方法区内存中)
二.JS的数据类型具体分类:
-
数值(number):整数和小数(比如
1
和3.14
)(类似Java的byte/short/int/float/double/long全部数值类的一起梭哈)
-
字符串(string):文本(比如
'Hello World'
)。 -
布尔值(boolean):表示真伪的两个特殊值,即
true
(真)和false
(假) -
undefined
:表示“数值未定义”,即undefined由于目前数值没有任何值,是作为默认值 -
null
:表示"空值对象不存在",即此处的对象值为空。 -
对象(object):各种值组成的集合。
-
symbol (symbol ) : 唯一标识符 //es6学习前不做讨论
PS1:数值、字符串、布尔值这三种类型,合称为原始类型(primitive type)的值,即它们是最基本的数据类型,不能再细分了。
PS2:对象Object则称为合成类型(complex type)的值,因为一个对象往往是多个原始类型的值的合成,可以看作是一个存放各种值的容器。
PS3:至于undefined和null,一般将它们看成即是两个数据类型,又是两个属性值。
1.深入Number 类型.(整数和浮点数值)
(类似Java的byte/short/int/float/double/long全部数值类的一起梭哈,也因此会出现精度丢失问题无法分辨,因此很多小数计算都会出现问题,因此计算数据不能在前端进行,只能在服务端上精准实现)
各种进制问题:
十进制
var num = 9;
进行算数计算时,八进制和十六进制表示的数值最终都将被转换成十进制数值。
十六进制
var num = 0xA;
数字序列范围:0~9以及A~F
八进制
var num1 = 07; // 对应十进制的7
var num2 = 019; // 对应十进制的19
var num3 = 08; // 对应十进制的8
数字序列范围:0~7
如果字面值中的数值超出了范围,那么前导零将被忽略,后面的数值将被当作十进制数值解析
①浮点数的精度问题(精度丢失问题严重)
浮点数
var n = 5e-324; // 科学计数法 5乘以10的-324次方
浮点数值的最高精度是 17 位小数,但在进行算术计算时其精确度远远不如整数
var result = 0.1 + 0.2; // 结果不是 0.3,而是:0.30000000000000004,js很奇葩...
console.log(0.07 * 100);
不要判断两个浮点数是否相等
java因为数值数据类型有着从小到大严格体系 , 因此只在数据类型强制转换(大转小)的时候,才会出现精度丢失问题.
②浮点数值精度深入(了解浮点数值的最高精度是17位的小数)
根据国际标准 IEEE 754,JavaScript 浮点数的64个二进制位,从最左边开始,是这样组成的。
- 第1位:符号位,
0
表示正数,1
表示负数 - 第2位到第12位(共11位):指数部分
- 第13位到第64位(共52位):小数部分(即有效数字)
符号位决定了一个数的正负,指数部分决定了数值的大小,小数部分决定了数值的精度。
指数部分一共有11个二进制位,因此大小范围就是0到2047。IEEE 754 规定,如果指数部分的值在0到2047之间(不含两个端点),那么有效数字的第一位默认总是1,不保存在64位浮点数之中。也就是说,有效数字这时总是1.xx...xx
的形式,其中xx..xx
的部分保存在64位浮点数之中,最长可能为52位。因此,JavaScript 提供的有效数字最长为53个二进制位。
(-1)^符号位 * 1.xx...xx * 2^指数部分
上面公式是正常情况下(指数部分在0到2047之间),一个数在 JavaScript 内部实际的表示形式。
精度最多只能到53个二进制位,这意味着,绝对值小于2的53次方的整数,即-253到253,都可以精确表示。
③浮点数值值范围(了解)
根据标准,64位浮点数的指数部分的长度是11个二进制位,意味着指数部分的最大值是2047(2的11次方减1)。也就是说,64位浮点数的指数部分的值最大为2047,分出一半表示负数,则 JavaScript 能够表示的数值范围为21024到2-1023(开区间),超出这个范围的数无法表示。
如果一个数大于等于2的1024次方,那么就会发生“正向溢出”,即 JavaScript 无法表示这么大的数,这时就会返回Infinity
正无穷大。
(3)Number的数值最大值和最小值
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Jfx7Mkiy-1620233715691)(C:\Users\tuyue\AppData\Local\Temp\1614854370842.png)]
Number最小值:Number.MIN_VALUE,这个值为: 5e-324 这个e代表10的幂的指数,即5*10^-324次方
Number最大值:Number.MAX_VALUE,这个值为: 1.7976931348623157e+308 即1.7976931348623157*10^308
无穷大:Infinity
无穷小:-Infinity
(4)用isNAN方法进行Number数值类型判断:
因为js是弱类型语言,所以很松散无厘头,竟然支持非法计算:“数值-字符串” 这种,只能用NAN去代表你这不是数值,是非法数.
-
1.NaN值:not a number (非法数值)
PS1:NAN通常在非法的数值计算会出现.
PS2:NaN 与任何值都不相等,包括他本身(即NAN===NAN 是为false的)
-
2.isNaN方法:是一个方法用来判断是否为NAN非法数值.
PS:方法返回的是一个布尔类型
PS:如下例子
<script>
var x = 10;
var y = 10 - 'f';//js无厘头支持非法计算:数值-字符串
console.log(y)//这种非法计算,会得出NAN非法数值
//NAN非法数很特殊,NAN与任何值都不相等,包括NAN本省
console.log(typeof y === 'NaN'); //false NAN与任何数都不相等
console.log(y === NaN); //false NAN与NAN自身比较也无法相等
//不要弄混
//上面是指NAN不能拿来比较的问题(也不是不能比较而是NAN和任何数比较都为false)
// 下面是指一个参数是不是NAN非法数的问题.
//只能通过isNAN方法,通过返回布尔类型,来判断一个实/形参数,是不是 ("非法数")
console.log(isNaN(y)); //true 是非法数
console.log(isNaN(NaN)); //true 是非法数
console.log(isNaN("小明")); //true 是非法数,因为该文字字符串无法转为数字
console.log(isNaN(10)); //false 不是非法数 ,是整数
console.log(isNaN("10")); //false 不是非法数,可以转为整数
console.log(isNaN(true)); //false 不是非法数,可以转为1
<script/>
PS:下面就是直接的语法报错了,变量没声明也没赋具体值,就拿去输出的…
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LvKLCbyT-1620233715693)(C:\Users\tuyue\AppData\Local\Temp\1614864192731.png)]
2.深入String字符串类型
1.一般很少转义,因为JS里面可以单引号和双引号一起使用,因此内容要使用双引号的时候,我们外层就单引号就OK
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-to9SAHUj-1620233715700)(C:\Users\tuyue\AppData\Local\Temp\1614878457990.png)]
2.还可以使用转义符转义中文和符号:
https://www.bejson.com/convert/unicode_chinese/
注: Unicode 码表查询地址 https://www.ltool.net/characters-to-unicode-charts-in-simplified-chinese.php
-
(3)获取字符串长度 (只读,无法修改)
length属性用来获取字符串的长度
var str = '海牙 Hello World'; console.log(str.length);
-
(4)按数组下标取字符串某个值(但也是只读,无法修改改写)
var str = 'hello world!'; console.log(str[1]); //e str[1] = 'x'; //无法改写
-
(5)如何字符串拼接
字符串拼接使用 + 号连接
console.log(11 + 11); console.log('hello' + ' world'); console.log('100' + '100'); console.log('11' + 32); console.log('male:' + true);
-
两边只要有一个是字符串,那么+号就是字符串拼接功能
-
两边如果都是数字,那么+ 号就是算术功能。
-
-
(6)关于字符串的换行,(一个字符串双引号内 , 无法直接换行)
//要不就一个引号一个引号的内容好好写 var longString = '第一行 ' + '第二行 ' + '第三行 ' + '文本内容'; //用反斜杠形式进行,一个字符串引号内可以换行 var longString = '第一行 \ 第二行 \ 第三行 \ 文本内容'; longString //
3.深入Boolean布尔类型
布尔值代表“真”和“假”两个状态。“真”用关键字
true
表示,“假”用关键字false
表示。布尔值只有这两个值。
4.Undefined和Null的区别!
1.(null是js弃子,Undefined才是相当于其他语言的null)
null
与undefined
都可以表示“没有”,含义非常相似。将一个变量赋值为undefined
或null
,老实说,语法效果几乎没区别。
- undefined表示一个声明了没有赋值的变量,变量只声明的时候值默认是undefined.
(只要不是null, 都会声明都会预分配内存了, 只是未定义但有默认值undefined) - null表示一个空,变量的值如果想为null,必须手动设置null.
(释放内存,不占位置,不让你占)
(java里面,null表示对象没了,为空,则会出现空指针异常,被gc垃圾回收器回收掉,即也是释放内存一种手段)
java中大体分为,基本数据类型和引用数据类型,
java中细分为(局部变量)/(实例变量)
1.基本数据类型(int i),声明它就在栈中分配了空间,当运行时,还会附上初始值.
2.引用数据类型(Object obj):在声明它的时候即那个局部变量引用,也是在栈中分配内存空间,用来存储内存地址,
①如果没有赋值该地址指向一个默认值空值(null),这和js的undefined一样作用.!!!!
②如果赋值,则该地址指向存储在堆中分配的地址,即开始new对象时,则在堆中就会开辟分配一个新内存地址给对象,
③如是其他对象赋值给它的,这时只是栈中的地址和原地址指向同一个堆,并没有在内存中分配新的堆空间(这也叫浅拷贝,引用复制)
④深拷贝:
3.
局部变量:(局部私有变量)
定义在方法中或方法的参数列表(或者语句中)
存在于栈内存中,作用的范围结束,变量空间自动释放,方法结束,自动销毁
默认没有初始化值,使用时需要进行初始化
实例变量又称成员变量:(this有关)
成员变量定义在类中,在整个类中都可以被访问
成员变量随着对象的建立而建立,随对象的消失而消失,存在于对象所在的对内存中
成员变量有默认初始值
静态变量又称类变量:用static修饰
存储在方法区中
随着类的加载而存在,随着类的消失而消失
可以由类名或对象调用
伪代码说明:
public class Variable{
static int a = 0; //静态变量,默认0
String b = "hello world";//实例变量,默认null
Wife w ; // w是实例变量 Variable有一个妻子
public void method(){
int c = 0; //局部变量
Variable var = new Variable(); // var也是局部变量来的
}
}
本文介绍成员变量和局部变量的区别:
1、成员变量是独立于方法外的变量,局部变量是类的方法中的变量
1)、成员变量:包括实例变量和类变量,用static修饰的是类变量,不用static修饰的是实例变量,所有类的成员变量可以通过this来引用。
2)、局部变量:包括形参,方法局部变量,代码块局部变量,存在于方法的参数列表和方法定义中以及代码块中。
2、成员变量可以被public,protect,private,static等修饰符修饰,而局部变量不能被控制修饰符及 static修饰;两者都可以定义成final型。
3、成员变量存储在堆,局部变量存储在栈。局部变量的作用域仅限于定义它的方法,在该方法的外部无法访问它。成员变量的作用域在整个类内部都是可见的,所有成员方法都可以使用它。如果访问权限允许,还可以在类的外部使用成员变量。
4、局部变量的生存周期与方法的执行期相同。当方法执行到定义局部变量的语句时,局部变量被创建;执行到它所在的作用域的最后一条语句时,局部变量被销毁。类的成员变量,如果是实例成员变量,它和对象的生存期相同。而静态成员变量的生存期是整个程序运行期。
5、成员变量在累加载或实例被创建时,系统自动分配内存空间,并在分配空间后自动为成员变量指定初始化值,初始化值为默认值,基本类型的默认值为0,复合类型的默认值为null。(被final修饰且没有static的必须显式赋值),局部变量在定义后必须经过显式初始化后才能使用,系统不会为局部变量执行初始化。
6、局部变量可以和成员变量 同名,且在使用时,局部变量具有更高的优先级,直接使用同名访问,访问的是局部变量,如需要访问成员变量可以用this.变量名访问
成员变量和局部变量的区别:
1、静态变量。bai 由static修饰du的变量称为静态变量,zhi其实质上就是一个全dao局变量。如果某个zhuan内容是被所有对象所共shu享,那么该内容就应该用静态修饰;没有被静态修饰的内容,其实是属于对象的特殊描述。
2、成员变量
研究一个事物(类),其有:
属性:外在特征;例如人的身高,体重,(对应class成员变量)
行为:能够做什么;例如人有说话,打球等行为。(成员函数)
3、成员变量和静态变量的区别
1、两个变量的生命周期不同
成员变量随着对象的创建而存在,随着对象被回收而释放。
静态变量随着类的加载而存在,随着类的消失而消失。
2、调用方式不同
成员变量只能被对象调用。
静态变量可以被对象调用,还可以被类名调用。
3、别名不同
成员变量也称为实例变量。
静态变量也称为类变量。
4、数据存储位置不同
成员变量存储在堆内存的对象中,所以也叫对象的特有数据。
静态变量数据存储在方法区(共享数据区)的静态区,所以也叫对象的共享数据。
2.历史原因:
在javascript设计初期 null
就像在 Java 里一样,被当成一个对象。初像 Java 一样,只设置了null
表示"无"。根据 C 语言的传统,null
可以自动转为0
。 但是javascript并没有完整的ERROR机制 null
可以转换为0 对于javascript这种弱类型的语言来说 不利于发现bug 所以设计了 undefined
变量默认值也就成为了 undefined
所以在学习javascript的过程中 不能用java等编程语言的null
来理解javascript中的null
在javascript中 null是 对象的延伸 是一个 ‘空’ 对象。var str = '';
中 ''
不能用null判断 他是有值的 内存中分配了空间来存储 ''
一个空字符串值。
null
在javascript中常见于释放内存空间和不传参数 var str = null;
3、目前的undefined和null各自用法
但是,上面这样的区分,在实践中很快就被证明不可行。目前,null和undefined基本是同义的,只有一些细微的差别。
null表示"没有对象了,对象没了",即该处不应该有值。 典型用法是:
(1) 作为函数的参数,表示该函数的参数不是对象了。
(2) 作为对象原型链的终点(释放内存)。
Object.getPrototypeOf(Object.prototype) // null
**undefined表示"缺少值",就是此处应该有一个值,但是还没有定义。**典型用法是:
(1)变量被声明了,但没有赋值时,就等于undefined。 js特有
(2) 调用函数时,应该提供的参数没有提供,该参数等于undefined。 js特有
(3)对象没有赋值的属性,该属性的值为undefined。 =java的null
(4)函数没有返回值时,默认返回undefined。 js特有
var i; i // undefined function f(x){console.log(x)} f() // undefined var o = new Object(); o.p // undefined var x = f(); x // undefined
三.一个值的类型判断
JavaScript 有三种方法,可以确定一个值到底是什么类型。
typeof
运算符 (最常用)instanceof
运算符 (亲子鉴定)Object.prototype.toString
方法
1.typeof(什么值的类型都能判断,死记下面的总结)
1.数值(含NAN非法数)、字符串、布尔值分别返回小写的
number
类型、string
类型、boolean
类型,2.undefined
值 和 未定义的变量 返回
undefined 类型,3.array数组和object对象都是 返回的是 object类型
4.null
值 返回
object 类型 //js的null很坑,null在js是归为对象object类型PS1:关于 null 在关系运算和相等运算中的坑:
null > 0 // null 尝试转型为number , 则为0 . 所以结果为 false, null >= 0 // null 尝试转为number ,则为0 , 结果为 true. null == 0 // null在设计上,在此处不尝试转型. 所以 结果为false.
PS2: isFinite
对于其他的数值(包括:null空值)都会返回
true`
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>类型判断 typeof isNaN isfinite</title>
</head>
<body>
<script>
//typeof 什么都能判断.
//判断数据类型
console.log(typeof String); //function函数String类接口
console.log(typeof Number); //function函数Number类接口
console.log(typeof Object); //function函数 Object类接口
console.log(typeof Boolean); //function函数Boolean类接口
function fn() {}
console.log(typeof fn);//function
console.log(typeof 'string'); //string类型
console.log(typeof 'number'); //string类型
console.log(typeof 'object'); //string类型
console.log(typeof 'boolean'); //string类型
//正常如果直接打小写的数据类型boolean出来会当成一个未定义的数值报错,
//但是typeof例外,未定义的也能判断并且不报错
console.log(typeof string); //undefined类型
console.log(typeof number); //undefined类型
console.log(typeof object);//undefined类型
console.log(typeof boolean); //undefined类型
//即是类型又是属性值的
console.log(typeof undefined);//即为属性值,同时还是undefined类型
console.log(typeof null); //即为属性值,但js把null归为object类型,很乱
//特殊的属性值
console.log(typeof null); //即为属性值,但js把null归为object类型,很乱
console.log(typeof NaN);//NaN归为number类型
//1.通过借用判断属性值,来判断类型
console.log(typeof 1); //number
console.log(typeof '1'); //string
console.log(typeof false); //boolean
console.log(typeof NaN);//NaN归为number类型
//2.通过判断表达式结果即也是属性值,来判断类型
console.log(typeof 'abc'.length); //number
console.log(typeof (1 < 2) );//boolean
//PS:这里已经不是typeof了,而是先typeof的表达式结果是什么类型,再次进一步判断===问题
console.log(typeof (1 < 2) === "boolean" ); //true
//为什么是true,普及!!!
//因为console.log打印出来的结果是转化为字符串的,
//如果直接打小写的数据类型boolean出来会当成一个未定义的数值报错
//而===是严格比较,比完类型,不同直接false,相同再比数值大小然后再是否相等
//==是宽松比较,比完类型不同,也会一直帮你自动转换类型,看看尽力帮你相等
//如下例子:
console.log("boolean" === "boolean" ); //true
console.log(typeof (1 < 2) === boolean ); //报错,boolean未定义
console.log(1==1);//true
console.log(1===1);//true
console.log(1=="1");//true
console.log(1==="1");//false
console.log(1 === true );//false 类型不同,直接pass
console.log(1 == true );//true true转为1,1=1
console.log("1"=== true );//false 类型不同直接pass
console.log("1" == true ); //true true转为1,"1"转为1
//甚至可以
console.log(typeof a); //可以判断未声明的变量类型,undefined
console.log(typeof b); //可以判断未声明的变量类型undefined
console.log(typeof c);//可以先斩后奏 类型为undefined
var c = 'x';
console.log(typeof c);// string类型
console.log(typeof c === 'number' && isNaN(x));//false
console.log(isFinite(null)); //true
var x = 1;
console.log(x + null);
</script>
</body>
</html>
typeof 甚至可以针对未声明的v变量而不报错的 , 只是会定义为undefined类型.
if (typeof v === "undefined" ) {
console.log("变量 v 不存在")
}
2.isNaN (isNAN主要是用来判断number数值类型是否为NAN,并返回一个布尔类型)
因此用来判断其他类型没有意义 ,因为isNAN判断其他类型都会触发Number()方法先,看能否先转为number数值,再去看是否为NAN非法数,是则true)
isNaN
方法可以用来判断一个值是否为NaN
非法数。
//isNAN判断其他类型都会触发Number()方法
console.log(isNaN(NaN));// true 已经是NAN了...
isNaN(123) // false 123数值
isNaN('123') // flase 数字字符串可以转123
// 触发了Number方法相当于
isNaN(Number('123')) // false
isNaN('Hello') // true 文字字符串不可转数值
// 触发了Number方法相当于
isNaN(Number('Hello')) // true
这一点要特别引起注意。也就是说,isNaN
为true
的值,并不代表数值就是NaN
这个值,
而是有可能是一个文字字符串,数组,对象等。如下
//下面代码之所以返回false不是非法数,统一的原因都是这些触发Number函数全部转成数值.
//Array数组
x=[];
console.log(isNaN(x)); //false ,空数组自身不是非法数
x=[123];
console.log(isNaN(x)); //flase , 数值数组不是非法数
x=["123"];
console.log(isNaN(x)); //false ,数值字符串数组不是非法数
x=["xyz"];
console.log(isNaN(x)); //true ,文字字符串数组是非法数
x=["哈哈哈"];
console.log(isNaN(x)); //true ,文字字符串数组是非法数
x=[{s}];
console.log(isNaN(x)); //true ,对象数组是非法数
//对象obj
x={};
console.log(isNaN(x)); //true ,对象都是非法数
var s;
s = new String();
x={s};
console.log(isNaN(x)); // true ,对象都是非法数
//String字符串,看是什么字符串
x=" ";
console.log(isNaN(x)); //false ,空字符串是不是非法数
x="xyz";
console.log(isNaN(x)); //true
x="123";
console.log(isNaN(x)); //false
</script>
因此,综上所处,使用isNaN
之前,最好判断一下数据类型。
(因为isNAN就是用来判断是不是NAN这个具体数值的,而不是判断文字字符串和数组和对象是不是NAN的,没意义了.)
function myIsNaN(value) {
return typeof value === 'number' && isNaN(value);
//这个 && 要同时为true才返回true, 因此如果typeof value不是===一个number 就已经可以返回flase了
//已经没有比较意义了,要在前面typeof value === 'number'这个成立为true,即为数值时,才去
//下一步isNaN(value)到底是不是NAN这一操作.
}
判断NaN
更可靠的方法是,利用NaN
为唯一不等于自身的值的这个特点,进行判断。
function myIsNaN(value) {
return value !== value;
//这里return 表达式是用于表示判断是否相等,如果相等返回true即value不是NAN,因为NAN不与任何数相等
}
3.isFinite(是否为正常范围的有限数字)
isFinite
方法返回一个布尔值,表示某个值是否为正常的数值。
isFinite(Infinity) // false
isFinite(-Infinity) // false
isFinite(NaN) // false
isFinite(undefined) // false
isFinite(null) // true
isFinite(-1) // true
①除了Infinity
无穷大、-Infinity
无穷小、NaN 非法数(非法不正常) undefined
未定义(即有可能是无穷大小)
这几个值会返回false
,
②isFinite
对于其他的数值(包括:null空值)都会返回true
。
四.数据类型的显式转换
1.首先先要分辨出数据类型的值在浏览器的颜色,然后再去测试;
chrome浏览器中 不同类型的值 打印颜色不同
String字符串的颜色是黑色的,
Number数值类型是蓝色的,布尔类型也是蓝色的,
undefined和null类型是灰色的
2.如何显式转换成String字符串类型
-
toString(包装类的方法转) 很常用
var num = 5; console.log(num.toString()); //Boolean也有包装类对象,true/false值也能toString()转
-
String(强制转) 很少用
String()函数存在的意义在于:有些值没有toString(),这个时候可以使用String()。 比如:undefined和null没有
-
(隐式特殊)拼接+ 号来然后拼接字符串方式: 整体就能变为字符串了
num + " “,(” "空字符串也有意义的,也会分配一个内存给他的,比如var num = " "; 默认值会给undefined )
当 + 两边其中一个操作符是字符串类型,一个操作符是其它类型的时候,也会先把其它类型转换成字符串再进行字符串拼接,返回字符串.
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-26rnlnfN-1620233715703)(C:\Users\tuyue\AppData\Local\Temp\1615034677240.png)]
3.如何显式转换成Number类型(分整数和浮点数)
-
推荐Number(); (包装类方法,不智能识别,有严格规范)
Number()可以把任意值转换成数值,如果要转换的字符串中只要有一个不是数值的字符,返回NaN. PS:Number()方法不会智能筛选不规范的数值类型,只要不规范全部是NAN非法数. 但是,更推荐使用,因为不规范的数值你智能筛选出来也是不是原始数据的脏数据了,没有用. 还不如是规范就规范,不规范就变为NAN. ①undefined 和 {}空对象 和不规范的数值和字符串 都是 Number转为NAN先. ②空数组[] 和 空字符串"" 和 null 和 0 和 false 都是Number转为 0先 ③true=1 和 fasle=0
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>类型转换 number</title>
</head>
<body>
<script>
// console.log(parseInt(13.133));//13
// console.log(parseInt('13.133'));//13
// console.log(parseInt('13.13u'));//13
// console.log(parseInt('1k3.13u'));//1
// console.log(parseInt('0100')); // 100
// console.log(parseInt('k13')); //NaN
// console.log(parseFloat(13.133));//13.133
// console.log(parseFloat('13.133.133'));//13.133 ,只识别规范范围内的小数
// console.log(parseFloat('13.13u'));//13.13
// console.log(parseFloat('1k3.13u'));//1
// console.log(parseFloat('0100')); // 100
// console.log(parseFloat('k13')); //NaN
console.log(Number(13.133));//13.133 规范浮点数
console.log(Number(13));//13 规范整数
console.log(Number('13.133.133'));//NaN
console.log(Number('13.13u'));//NaN
console.log(Number('1k3.13u'));//NaN
console.log(Number('0100')); // 100
console.log(Number('k13')); //NaN
console.log(~~'33' ); //33 位运算两次反转,即不变
console.log('33'*1 ); //33 乘1,即也不变
console.log('33' - 0); // 33 减0 ,即也不变
console.log('33' + 0); //"330"
//切记,面对字符串不能+ ,否则同化一定变为字符串
</script>
</body>
</html>
// !-[-1,] 数组
console.log(Number([-1])); //-1
console.log(Number([1])); //1
console.log(+[-1]); //-1
console.log(-[-1]); //1
console.log(-[-1,]); //1
console.log(Number([-1,-2])); //NAN
console.log(+[-1,-2]);//NAN
这种既不声明也不赋值的变量a,就是使报错的语法.
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qgfoMCEb-1620233715708)(C:\Users\tuyue\AppData\Local\Temp\1615104454570.png)]
-
parseInt(智能识别转为int整数,不保留小数位)
var num1 = parseInt("12.3abc"); // 返回12,如果第一个字符是数字会解析知道遇到非数字结束 var num2 = parseInt("abc123"); // 返回NaN,如果第一个字符不是数字或者符号就返回NaN
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uGtWJitt-1620233715709)(C:\Users\tuyue\AppData\Local\Temp\1615035285109.png)]
-
parseFloat(智能识别转为float浮点数,且保留小数位)
1.parseFloat()和parseInt转化规则非常相似,不同之处在与 parseFloat只会解析第一个小数点. 遇到第二个不规范小数点就不识别砍掉了. 2.如果解析的内容里只有int整数,则和解析成整数parseInt 3.第一个数字不是数字,就直接NAN.
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lC6RGHpj-1620233715711)(C:\Users\tuyue\AppData\Local\Temp\1615035523863.png)]
-
(隐式特殊)+0,-0等运算 ,不用Number()方法
-
巧妙直接用"一元加减运算符" 转换为数值类型. 不用Number()方法.
//原理:一元加+和减-操作符对于非正常数值,会触发Number()转类型,不能乱加有影响 var str = '500'; console.log(+'500'); // 字符串加上一元加运算符,变为 取正 console.log(-'500'); // 字符串加上一元减运算符,变为 取负 console.log('500' - 0); //其他一元运算符骚操作,变为数值类型.了解借壳 console.log(~~'33' ); //33 位运算两次反转,即不变 console.log('33'*1 ); //33 乘1,即也不变 console.log('33' - 0); // 33 减0 ,即也不变 console.log('33' + 0); //"330" //切记,面对字符串千万不能使用 +拼接 ,否则一定同化变为字符串
4.如何显式转换成Boolean布尔类型
-
①Boolean()方法.
死记规则: 除了 “空字符串” / 0 / false / undefined / null / NAN 是false; 消极的都是false
其他任何的值转换为布尔值 都是 true;<script> console.log(Boolean(1)) //true console.log(Boolean(true)) //true console.log(Boolean("哈哈")) //true console.log(Boolean("123")) //true console.log(Boolean(123)) //true console.log(Boolean([])) //true console.log(Boolean(["x"])) //true console.log(Boolean([1])) //true console.log(Boolean({})) //true console.log(Boolean(" ")); //true 这里不是空字符串了 console.log(Boolean("")) //false 是空字符串 console.log(Boolean(0)); //false console.log(Boolean(false)); //false console.log(Boolean(null)) //false console.log(Boolean(undefined)) //false console.log(Boolean(NaN)); //false </script>
五.数据类型的隐式转换
(即本来是通过上面明显的数据类型的方法函数去转换数据类型,但是通过一个操作符也能让隐式转任何类型,骚操作)
(很难受,即操作符正常使用下你还得额外考虑隐转)
一.如何隐式转化任意类型为number类型:(用+/++和-/-- 一元加和自增运算符)
1.①上述一元运算符会触发Number()方法隐转再加减运算 (从而达到不直接用Number()方法转)
(②isNAN方法也是先会触发Number()方法先,看能否先转为number数值,再去看是否为NAN非法数,是则true))
2.具体规则:
/*一元加和自增运算符的隐式规则其实就和Number函数转化的规则一样:
①undefined 和 {}空对象 和不规范的数值和字符串 都是 Number转为NAN数值先,再去加减
②空数组[] 和 空字符串"" 和 null 和 0 和 false 都是Number转为0数值先,再去加减 */
-
如果包含的是有效数字字符串或者是有效浮点数字符串,则会将字符串**(通过Number()函数)**转换为数值,再进行加减操作,返回值的类型是:number类型。
-
如果不包含有效数字字符串,则number函数会将字符串的值转换为NaN非法数,返回值的类型是:number类型。
-
如果是boolean类型,则先会把true或者false隐式转换为1或者0,再进行加减操作,返回值的类型是:number类型。
-
如果是null类型,则先会把null隐式转换为0,在进行加减操作,返回值的类型是:number类型。
-
如果是undefined,则先会把undefined转换为NaN,再进行加减操作,返回值的类型是:number类型。
-
如果是obj对象,则先会通过对象的valueOf()方法,进行转换,如果返回的是NaN非法数,再去调用toString()方法,在进行前面的操作,返回值的类型是:number类型.
3.代码案例:
<script>
// ++x x++ --x x--
//一元运算符,+ 和++ 都会触发number函数,不规范的数值直接NAN.(null是被当成0)
var x = "4";
console.log(+x); //4
console.log(++x); // 5
//等同 console.log(Number("4")); -> 然后再+/++加减
x ="4jdj";
console.log(+x); //NAN ,触发number函数,不规范的数值直接NAN
console.log(++x); //NAN
//等同 console.log(Number("4jdj")); -> 然后再+/++加减
x = false;
console.log(+x); // 0
console.log(++x); // 1
//等同 console.log(Number(false)); -> 然后再+/++加减
x = true;
console.log(+x); // 1
console.log(++x); // 2
//等同 console.log(Number(true)); -> 然后再+/++加减
x = undefined;
console.log(+x); //NaN
console.log(++x); //NaN 重点 undefined数字运算隐式转换是为NAN的
//等同 console.log(Number(undefined));//NaN -> 然后再+/++加减
x = null;
console.log(+x); //0 重点 undefined数字运算隐式转换是为0的
console.log(-x); // -0
console.log(++x); //1
//等同 console.log(Number(null));//0 -> 然后再+/++加减
x=[]; //空数组
console.log(+x); //0
console.log(++x); //1
//等同 console.log(Number([])); //0 -> 然后再+/++加减
x=" "; //空字符串
console.log(+x); //0
console.log(++x); //1
//等同 console.log(Number(" "));//0 -> 然后再+/++加减
x={}; //空obj对象
console.log(+x); //NaN
console.log(++x); //NaN
//等同 console.log(Number( {} ));//NaN -> 然后再+/++加减
</script>
二.如何隐式转换任意数据类型为Boolean类型 (通过&& || ! !!与或非逻辑运算符)
1.隐式转换布尔类型(不用Boolean()方法达到)
流程控制语句会把后面的值 隐式转换成布尔类型
复习:Boolean布尔类型的隐式转换.
能转换成false的既能转为0的 : 变为 ""空字符串 0 false null undefined NaN (有关消极的)
剩下的相反都能转换为true的 : 变为 "x"非空字符串 非0数字(包括任何负数和整数) true 任何非空obj对象
//PS:任何非0数值可以隐转转为true布尔类型,但true相反只能转为1 number数值
console.log(true); //true
console.log(+true); //1
console.log(-true); //-1
console.log(!10); //false ,10转true
console.log(!-10); //false ,-10转true
console.log(!0); //true , 0转false
if(x=10) // 返回true
if(x=-10) // 返回true
if(x=0) // 返回false
// 实际最常用的隐式转换布尔类型手段(用! 和 !!,方便直接)?
var a = !'123'; //tfalse , !就是看Boolean的结果取反, 把"123"转为布尔true了,再取反变为布尔false了
var a = !!'123'; //true , !!就是看Boolean的结果即可, 把"123"转为布尔true了
2.具体规则:
/*1.具体规则:
//&&和|| (不常用,结果可能不是布尔,无法确保能转为Boolean)
//因为都是先拿左边的值去进行布尔类型Boolean函数转换尝试,右边可以不动原值的
//再是进行逻辑操作符比较: (余座真饭友 , 或座真反击)
//注意:最后输出是输出原始值的,不是看转换的值,转换值只是我们自己计算时需要而已.
2 !和!! (最常用,结果一定是布尔)
!都是拿值去进行布尔类型Boolean方法转换尝试,结果取反即可.
如果是!!直接就是布尔类型boolean的转换结果了.(自己细品)
逻辑操作符一般用于语句判断中。通过判断结果返回的值进行后面的语句操作。
-
逻辑非(!)操作符:首先会通过Boolean()函数将其操作值转换为布尔值,然后求反。
-
逻辑与(&&)操作符:如果第一个值经过Boolean()函数转换后为true,则返回第二个操作值,否则返回第一个操作值。如果有一个操作值为null这返回null,如果有一个操作值为undefined,则返回undefined,如果有一个值为NaN,则返回NaN。(与座真饭友)
-
逻辑或(||)操作符:如果第一个值经过Boolean()函数转换为false,则返回第二个操作值,true则返回第一个操作值。
(或座真反击)(注:逻辑操作符的运算为短路逻辑运算:前一个条件已经能够得出结果后续条件不再执行!)
3.代码案例:
<script>
String(num)[1] && String(num) || '0' + num;
// 字符串方法也能,像数组一样用下标取值,没有则返回undefined的.
// undefined && '1' || '01'
// false && '01' || '01'
// false || '01'
//'01'
console.log(1 && 2); //2
//1转为true ,然后&& 输出2
var x;
console.log(x && 2); //undefined
//undefined 先boolean转为false , 然后&& 输出undefined
var y = '0';
console.log(y && 2); //2
// '0'先boolean转为true,然后&& 输出2
console.log(1 && null); //null
//1转为true ,然后&& 输出null
console.log(null && 1); //null
//null转为false ,然后&& 输出null
console.log(1 || null); // 1
//1转为true, 然后|| 输出1
console.log(null || 1); // 1
//null转为false ,然后|| 输出1
//!都是拿值去进行布尔类型Boolean方法转换尝试,结果取反即可.
//如果是!!直接就是布尔类型boolean的转换结果了.(自己细品)
console.log(!!0); //false
console.log(!!''); //false
console.log(!NaN); //true
console.log(!!NaN); //false
console.log(!!undefined);//false
console.log(!!null); //false
</script>
三.关系操作符如何隐式转换 让任意数据类型都能去比较大小:
(这里就不是说隐式去转其他类型,而是注意关系操作符如何比较转化去大小,返回真假了,上面一和二才是实用功能的,能通过+和!!来隐式转number和Boolean,关系运算符会出现各种类型组合的隐式转化问题)
> < >= <= == !=
//尽量用 === 做对比判断 ,不要使用==,因为==隐式很多你不理解的bug
// 1.准确 不会出现因为隐式转换而产生的的乌龙事件 存在风险
// 2.性能原因 动态类型的语言 是语言性能瓶颈之一
var uid = true;
console.log(1 === uid); //false (必须类型和值同时相等才行,无法隐式转换)
1.具体规则:(死记,努力往数字number去转换)
-
两边全是数值数字,直接按顺序比
-
两边全是String数值字符串的,转number直接比即可
-
两边都是String文字字符串的,则字符串进行其Unicode编码进行比较。首字符
-
如果一个操作值是对象,则调用对象的valueOf()和toString()方法,然后再进行上述都是字符串的unicode比较。
-
一边number数值,一边Boolean布尔的,则也是都往number转,再比
-
一边String文字或者数字字符串, 一边数字,则都往number转,文字字符会变NAN,直接false
-
一边String文字或数字字符串,一边布尔的,则也是都往number转,再比
-
遇到NAN比较的,全部都是false ,除非有!取反全是true, !!变回全是false
-
在关系运算符!=/==和>=/<=中, null 和 0(包括能转0的)都是对着干的,真假结果颠倒.
总结: 基本都是努力往数字number去转换即可了
//尽量用 ===代替 == 做对比判断
//===要值和类型都得一样才等, ==只要最后转换的值一样即可,类型不管.
//1.准确 不会出现因为隐式转换而产生的的乌龙事件 存在风险
//2.性能原因 动态类型的语言 是语言性能瓶颈之一
var uid = true;
console.log(1 === uid); //false (必须类型和值同时相等才行,无法隐式转换)
3.代码案例:
<script>
//1.两边全是数值数字,直接按顺序比
console.log(3 < 1); // false ,直接比即可
console.log(3 < 2 < 1); //true 同级运算符要从左到右运行,
//① 3<2 是false
//② false < 1 是关系运算符隐式转换为0 < 1
//③因此最终结果为:true
//2.两边全是String数值字符串的
console.log("3" < "1"); // false ,转number直接比即可
//3.两边都是String文字字符串的
console.log('哈哈哈' == '哈哈哈'); //true
console.log('哈牙' < '哈哈哈'); //false
//两边都是文字字符串,对比unicode编码,首字母牙比第二个哈高,因此false
//如obj对象比,要用valueof方法转string字符串先再重复上面unicode这一步
//4.一边数值,一边布尔的,则也是都往number转,再比
console.log(2 < true); // 2 < 1 => false
//5.一边String文字或者数字字符串, 一边数字,则都往number转,文字字符会变NAN,直接false
console.log("哈哈" > 1); //false
console.log("1" < 1); //false
//6.一边String文字或数字字符串,一边布尔的,则也是都往number转,再比
console.log('0' == false);// true 0 == 0
console.log('哈哈' == false);// false NAN==0
console.log('0u' == false);// false NAN==0
//7.遇到NAN比较的,全部都是false ,除非有!取反全是true, !!变回全是false
console.log(NaN <= NaN); //fasle NaN和任何值 做任何对比 都是false
console.log(NaN == 1); //fasle NaN和任何值 做任何对比 都是false
console.log(NaN != NAN); //true
console.log(NaN != 1); //true
</script>
关系运算符一个超级特殊的点:
1.在关系运算符!=/==和>=/<=中, null 和 0(包括能转0的)都是对着干的,真假结果颠倒. 其他正常
2.仅仅在关系运算符==中(!=都不算), null 和 undefined都是对着干的,真假结果颠倒. 其他正常
//在关系运算符!=/==和>=/<=中 ,黑白颠倒
console.log(null <= []); //true , []要转为0的,对着干了,本来是false
console.log(null >= 0); //true , 本来是false
console.log(null == 0); //false ,本来是true的
console.log(null != 0); //true ,本来是false的
//除了!=/==和>=/<= ,在 >和< null和0是正常的
console.log(null > 0); //false ,在 >和< null和0是正常的
console.log(null < 0); //false ,在 >和< null和0是正常的
//然后除了不是0(包括能通过number转0),也都是一切正常的
console.log(null <= 1); //true ,
console.log(null == 1); //false
console.log(null < 1); //true
console.log(null == undefined); // true , 此处0 == NAN会颠倒黑白,本来是false的
console.log(null != undefined); //false,正常了
console.log(null >= undefined); //false,正常了
console.log(null <= undefined); //false,正常了
console.log(null > undefined); //false,正常了
console.log(null < undefined); //false,正常了
console.log(undefined >= -1); // false ,正常了
//NAN >= -1
参考原理 : http://bclary.com/log/2004/11/07/#a-11.9.3
- 关系运算符 和 相等运算符 并不是一个类别的. 关系>相等的
- 关系运算符,在设计上,总是需要运算元尝试转为一个number . 而相等运算符在设计上,则没有这方面的考虑.
- 最重要的一点, 不要把 拿 a > b , a == b 的结果 想当然的去和 a >= b 建立联系. 正确的符合最初设计思想的关系是 a > b 与 a >= b是一组 . a == b 和其他相等运算符才是一组. 比如 a === b , a != b, a !== b .
总结:相等操作符== 和 ===的隐式转换规律:
- 布尔值、字符串和数值进行比较,会先将其转换为number数值再进行比较。(上案例)
- NaN与任何值都不相等,老样子都会返回false。 (上案例)
- null和undefined比较是= =相等的true,但不是===全等的false。
console.log(null == undefined); // true 本来是false的,真假颠覆
console.log(null === undefined); // false ===不会出现隐式,正常
六.隐式转换大总结: (隐式转obj对象暂时不讲)
一元运算符: +35 -35 ++35 --35
二元运算符: 1+2 2-1
混合使用: 1+-2 -> 1+(-2) //-1
1+true -> 1+1 //2 true隐式转number数字1
1+ "true" -> //"1true" ,拼接符+让String变boss
1.通常用一元加减符+ -号(注意不是拼接的±二元符), 底层会触发Number函数,来让任何类型隐式转number数值类型
2.通常用! 和 !! ,底层触发Boolean函数,来让任何类型隐式转Boolean布尔类型
3.通常用二元拼接符+号 和 " " 组成: num + " " , 来让任何类型隐式转为String数值类型
4.关系运算符会出现各种类型组合的隐式转化问题,要特别重点复习和深刻记忆的.
**扩展第3点:**在有加+号拼接运算符的公式 ,可以让有String字符串的公式瞬间变绝对优势Boss,即当前+拼接符运算范围内结果一定会是拼接的String字符串,但其他地方字符串就是弱鸡,要字符串通过转number类型.
console.log('\u0035' + (true * 2) + false);
// String + (Number) + Boolean = +加号拼接只要有字符串,则当前+拼接符运算范围结果一定是拼接字符串
// '5' + 2 => '52' + false
// '52false'
console.log('\u0035' + (true * 2) + +false);
//让false布尔去隐式转换为0 , 即 "520"
console.log('5' - 2 + '3'); // '33'
// string - number + string
// '5'- 2 => 3 number
// 3 + '3' => '33'
//上面和下面的结果代表,不一定出现"",就代表结果一定是字符串的,看运算范围的
console.log(' ' + NaN - false + !-1);
// String + NaN - boolean + boolean
// ' NaN' - false
// NaN - 0
// NaN - 0 -0
// NaN
七:隐式转换的测试(自己品):
1 + true;
1 + 'true';
1 + undefined;
1 + null;
NaN == NaN;
undefined == null;
null !== undefined;
2 + '5' - 3;
6 > '3' == 3;
undefined == '0';
null == 0;
null >= 0;
parseInt('13.33') === ~~'13.33';
false - 1 <= '0';
'Value is ' + (val != '0') ? 'define' : 'undefine';
海牙老师练手测试:
<script>
console.log('\u0035' + (true * 2) + false);
// String + (Number) + Boolean = +加号拼接只要有字符串,则当前+拼接符运算范围结果一定是拼接字符串
// '5' + 2 => '52' + false
// '52false'
console.log('\u0035' + (true * 2) + +false);
//让false布尔去隐式转换为0 , 即 "520"
console.log('5' - 2 + '3'); // '33'
// string - number + string
// '5'- 2 => 3 number
// 3 + '3' => '33'
console.log(' ' + NaN - false + !-1);
// String + NaN - boolean + boolean
// ' NaN' - false
// NaN - 0
// NaN - 0 -0
// NaN
console.log(!-[-1,]); //false
//!-true
//!-1
//!true
//false
//三目运算符;
var val = 1;
console.log('Value is ' + (val != '0') ? 'define' : 'undefine'); //
//String + (1!="0") ? 'define' : 'undefine';
//String + Boolean ? 'define' : 'undefine';
//'Value is true' ? 'define' : 'undefine';
//true ? 'define' : 'undefine';
//'define'
console.log(false - 1 <= '0'); //true
//-1 <= "0"
//true
console.log(null >= NaN); // false
console.log(NaN >= NaN); // false
</script>
扩展:Java中obj引用的 toString(无参) 和String.valueOf(有参) 的区别:
Java中obj引用的 toString(无参) 和String.valueOf(有参) 的区别:
String str1 = obj引用.toString(); VS String str1 = String类.valueOf(obj对象/int基类);
toString(无参)和valueOf(有参)的区别就是;
1、大体讲:
①valueOf底层其实就是toString(无参/有参),能变"基本类型"和"obj对象"为String形式。
②而toString(无参)是只让obj对象变为字符串形式输出的方法)
③而valueOf(有参)实际包含着一部分的toString(无参)方法。
④共同点作用:都有一个相同的功能那就是可以把对象,转换和返回成String字符串形式输出
2、细致讲:
①一个无参数(内部的return转),实例方法要new对象,仅仅是改变对象自身输出形式的方法(里面是可以自己手写改对象的输出形式,但一定要字符串形式);
②一个有参数(直接形参外部转),静态方法用类调,将特定的“参数”转为字符串String,其实底层也是会去调"基类的包装类或者obj对象“重写的toString(无/有参)方法.
③因此综上:String.valueOf()有着独特优点:就是还可以把"基本类型"转换字符串String,而toString(无参)不能。
PS注意1:通过方法转型如果obj为null不会抛出NullPointerException异常;
而是将obj对象转换成"null"字符串。这样 str1 就被赋值为 "null",
这样乍一看没什么问题,感觉这样可以避免NullPointerException异常,如果后期要对str1要做其他类型的转换就会出问题。
比如:Integer.valueOf(str1);这是就会报错NumberFormatException提示数据类型转换出错(因为返回的字符串“null”无法转去Integer)。
到这里就会发现 String.valueOf()埋下的坑了。
所以一般情况下在使用这两个方法前最后都要考虑一下null值得情况,不然后期发现问题,改数据将是非常痛苦的。
PS注意2:**jdk里String.valueOf(Object/int i)源码如下:(底层是toString(有参/有参))
① public static String valueOf(Object obj) { return (obj == null) ? "null" : obj.toString(); }
//底层是toString(无参),调obj对象的toString(无参)方法(自定义类对象的话记得要自己重写toString)
②public static String valueOf(int i) { return Integer.toString(i);}
//底层是toString(有参),调基数的包装类的toString(有参)方法(不需要重写)
③而Object的toString()源码如下:
public String toString() { //仅仅只能是对象
return getClass().getName() + '@' + Integer.toHexString(hashCode());
}
PS注意3:这种方法套方法的套路:其实是一样的不要怕!
//正常写法:
Customer customer = new Customer();
String s = String.valueOf(customer);
System.out.println(s);
//这里valueOf(customer)底层一样会调customer的toString无参方法,和下面是一样的
System.out.println(customer); //这里和上面其实也一样,底层一样是调用customer的toString方法,是同一样的结果,只是一个静态一个实例
//方法套方法写法:
public String toString() { //把对象以字符串的形式输出;
return String.valueOf(11); // 这里底层就是再去调一次Integer包装类的
//toString(有参)转为字符串,返回即可。其实没变,也可以直接手打"id = " + id;
}
public String toString() { //把对象以字符串的形式输出;
return String.valueOf(new Vip(11));
//这回会报错, Exception in thread "main" java.lang.StackOverflowError
//因为String.valueOf(new Vip(11))实际底层会去调toString无参,即这个上面这个重写的public String toString()方法
//那么就会进入递归,如果没有条件限制,就会死循环栈溢出报错。
}
mberFormatException提示数据类型转换出错(因为返回的字符串“null”无法转去Integer)。
到这里就会发现 String.valueOf()埋下的坑了。
所以一般情况下在使用这两个方法前最后都要考虑一下null值得情况,不然后期发现问题,改数据将是非常痛苦的。
PS注意2:**jdk里String.valueOf(Object/int i)源码如下:(底层是toString(有参/有参))
① public static String valueOf(Object obj) { return (obj == null) ? “null” : obj.toString(); }
//底层是toString(无参),调obj对象的toString(无参)方法(自定义类对象的话记得要自己重写toString)
②public static String valueOf(int i) { return Integer.toString(i);}
//底层是toString(有参),调基数的包装类的toString(有参)方法(不需要重写)
③而Object的toString()源码如下:
public String toString() { //仅仅只能是对象
return getClass().getName() + ‘@’ + Integer.toHexString(hashCode());
}
PS注意3:这种方法套方法的套路:其实是一样的不要怕!
//正常写法:
Customer customer = new Customer();
String s = String.valueOf(customer);
System.out.println(s);
//这里valueOf(customer)底层一样会调customer的toString无参方法,和下面是一样的
System.out.println(customer); //这里和上面其实也一样,底层一样是调用customer的toString方法,是同一样的结果,只是一个静态一个实例
//方法套方法写法:
public String toString() { //把对象以字符串的形式输出;
return String.valueOf(11); // 这里底层就是再去调一次Integer包装类的
//toString(有参)转为字符串,返回即可。其实没变,也可以直接手打"id = " + id;
}
public String toString() { //把对象以字符串的形式输出;
return String.valueOf(new Vip(11));
//这回会报错, Exception in thread “main” java.lang.StackOverflowError
//因为String.valueOf(new Vip(11))实际底层会去调toString无参,即这个上面这个重写的public String toString()方法
//那么就会进入递归,如果没有条件限制,就会死循环栈溢出报错。
}