这篇博客主要包括数据类型、深拷贝&浅拷贝、数据类型的转换、toString()方法判断数据、相等与全等的区别。若有错误,欢迎指正。javascript
由于上次金山面试问了巨多这一块的内容,因此作个总结,零碎的知识点不少。这篇原本是上周先发在掘金的,可是掘金的排版器没有思否用着顺手,之后仍是在这里更。。。(唉出场顺序过重要了,我爱思否)html
null是对象类型仍是基本数据类java
1.基本数据类型有 number,string,boolean,null,undefined,symbol(ES6新增的),也称原始数据类型。面试
2.JS有原始值类型和引用值类型
2.1 原始值类型里面存储的都是值,原始值类型是没法改变的。
2.2 引用值类型指的是由多个值构成的对象。segmentfault
let str = "hello"; str[0] = "z"; //没法修改
通常状况下声明的变量是对象类型的话,会在栈内存中存放着引用地址,该地址会指向堆内存中的内容。
3.JS内存分为堆内存和栈内存,栈内存保存的都是有固定大小、空间的内容。堆内存中存储的都是不固定的内容。数组
4.两者区别
4.1 原始值类型保存在栈内存中,能够按值直接访问。
值与值之间是独立存在的,修改一个变量不会影响到其余变量。app
var a = 10; var b = a; //将a的值赋给b b = 20; console.log(a); // 10 console.log(b); // 20
① 基本数据类型赋值过程:函数
4.2 引用值类型存放在堆内存中,按照引用访问。spa
若是两个变量保存的是同一个对象引用,当经过一个变量修改属性时,另一个也会受到影响。.net
var obj = new Object(); obj.name = "孙悟空"; var obj2 = obj; obj2.name = "猪八戒"; console.log(obj.name); //猪八戒 console.log(obj2.name); //猪八戒
② 引用数据类型赋值过程:
5.若是两个对象如出一辙,但也仍是两个对象
6.null不是引用数据类型,是基本数据类型。
1.深拷贝: 修改新变量的值不会影响原有变量的值,默认状况下基本数据类型都是深拷贝
let num1 = 123; let num2 = num1; num2 = 666; // 修改新变量的值 console.log(num1); //123 console.log(num2); /666
2.浅拷贝:修改新变量的值会影响原有的变量的值,默认状况下引用类型都是浅拷贝。
class Person{ name = "jjj"; age = 23; } let p1 = new Person(); let p2 = p1; p2.name = "wdhj"; //修改p2的值影响了p1的值 console.log(p2.name); //wdhj console.log(p1.name); //wdhj
当引用数据类型中保存的都是基本数据类型时
如下三种方法并不能实现真正意义上的深拷贝,由于对象中保存的都是基本数据类型
1.方法一(很差)
浅拷贝的缘由:多个变量指向了同一块存储空间,想要实现深拷贝,可让每一个变量分别指向本身的存储空间
class Person{ name = "mss"; age = 18; } let p1 = new Person(); let p2 = new Person(); //由于p1里面的属性都是基本数据类型,因此能够取出p1的name赋值给p2 p2.name = p1.name; p2.age = p1.age; p2.name = "mhf"; p2.age = 20; console.log(p1.name); //mss console.log(p2.name); //mhf
2.方法二(很差)
利用循环来遍历每一个属性
class Person{ name = "mss"; age = 18; } let p1 = new Person(); let p2 = new Person(); for(let key in p1){ //利用遍从来赋值每一个属性 p2[key] = p1[key]; } p2.name = "mhf"; console.log(p1.name);//mss console.log(p2.name);//mhf
3.方法三(重点)
Object的assign()方法接收两个参数,表明含义是将p1中的全部属性拷贝到p2中
class Person{ name = "mss"; age = 18; } let p1 = new Person(); let p2 = new Person(); Object.assign(p2,p1); p2.name = "mhf"; console.log(p1.name);//mss console.log(p2.name);//mhf
当引用数据类型中保存的都是引用数据类型时
1.方法一:JSON.parse(JSON.stringify(obj))
2.方法二:手写深拷贝
1.Number(常量或者变量)
1.1 注意:
let str = Number('123'); console.log(str); //123 console.log(typeof str); //number
1.2 转换规则
2.数学运算符中的“+”、“-”
2.1 注意:
let str = "123"; let num = +str; console.log(num); //123 console.log(typeof num); //number
3.parseInt(字符串)和parseFloat(字符串)
3.1 注意:
let res = true; // let res = "true"; let num = parseInt(res); //把true当作字符串处理,没有遇到数字因此返回NaN console.log(num); //NaN
1.toString()
Number、Boolean类型可调用toString()转换为String类型
格式:变量名称.toString()
注意:
let value = 123; let str = value.toString(); console.log(str); //123 console.log(typeof str); //string console.log((3).toString()); //影响原有的数据
2.String()方法
格式: String(常量or变量)
注意:
let res = String(3); console.log(res); //3 console.log(typeof res); //string let str = String(undefined); console.log(str); //undefined console.log(typeof str); //string
3.常量/变量 + “”
利用 常量/变量 加上一个空字符串来转换,本质上是调用了String()函数, 不会修改原有的值
let value = 123; let str = value + ''; console.log(str); //123 console.log(typeof str); //string
Boolean(变量or常量)
注意:
总结:
空字符串/0/NaN/undefined/null会转换成false
1.undefined
和null
没有toString()
方法
console.log(undefined.toString()); //报错 console.log(null.toString()); //报错
2.Number
、Boolean
、String
等包装对象的toString()
方法;本地对象的toString()
方法
console.log(Number.toString()); //function Number() { [native code] } console.log(Boolean.toString()); //function Boolean() { [native code] } console.log(String.toString()); //function String() { [native code] } console.log(Function.toString()); //function Function() { [native code] } console.log(Array.toString()); //function Array() { [native code] } console.log(Object.toString()); //function Object() { [native code] } console.log(RegExp.toString()); //function RegExp() { [native code] } console.log(Date.toString()); //function Date() { [native code] }
3.整数直接跟上.toString()
形式会报错,提示无效标记,由于整数后的点会被识别为小数点
String()
方法console.log(3.toString()); //报错 console.log((3).toString()); //3 console.log(3..toString()); //3 let res = String(3); console.log(res); //3
4.Object.prototype.toString()
来进行类型识别,返回表明该对象的[object Type]字符串表示
toString()
方法,可是不能直接使用,由于对象有可能直接重写了此方法,必须使用call()或者apply()调用console.log(Object.prototype.toString.call("abc")); //[object String] console.log(Object.prototype.toString.call(1)); //[object Number] console.log(Object.prototype.toString.call(true)); //[object Boolean] console.log(Object.prototype.toString.call(null)); //[object Null] console.log(Object.prototype.toString.call(undefined)); //[object Undefined] console.log(Object.prototype.toString.call({})); //[object Object] console.log(Object.prototype.toString.call(function(){}));//[object Function] console.log(Object.prototype.toString.call([]));//[object Array] console.log(Object.prototype.toString.call(/\s/)); //[object RegExp] console.log(Object.prototype.toString.call(new Date));//[object Date] function Person(){} console.log(Object.prototype.toString.call(new Person));//[object Object]
5.除了类型识别以外,还能够进行其余识别,例如识别arguments或DOM元素
(function(){ console.log(Object.prototype.toString.call(arguments));//[object Arguments] })(); console.log(Object.prototype.toString.call(document));//[object HTMLDocument]
6.数组Array类型调用toString()
方法,返回由数组中每一个值的字符串形式拼接而成的一个以逗号分隔的字符串
console.log([1, 2, 3, 4].toString()); //1,2,3,4 console.log([].toString()); // 输出空
这时咱们能够用这个思路来将多维数组转为一维数组,注意数组中的每一项变为字符串了
let arr = [1,[2,[3,4],5],6]; // console.log(arr.join(",").split(",")); console.log(arr.toString().split(","));
1.两个值类型相同
若是两个值类型相同,再进行三个等号(===)的比较, 与严格相等运算符彻底同样。
2.两个值类型不一样
在比较不一样类型的数据时,相等运算符会先将数据进行类型转换,而后再用严格相等运算符比较。类型转换规则以下:
(1) 原始类型值比较
原始类型的数据会转换成数值类型再进行比较
① 若是有一个操做数是布尔值,则在比较相等性以前先将其转换为数值; false转换为0,而true转换为1console.log(true == 1); //true
② 若是一个操做数是字符串,另外一个操做数是数值,在比较相等性以前先将字符串转换为数值console.log('123' == 123);//true
(2) 对象与原始类型值比较
若是一个操做数是对象,另外一个操做数不是,则调用对象的toString()方法,用获得的基本类型值按照前面的规则进行比较
console.log([] == 0); //true console.log([].toString()); //空 console.log({} == 0); //false console.log( {}.toString()); //[object Object]
(3) undefined和null的比较
undefined和null与其余类型的值比较时,结果都为false,它们互相比较时结果为true。
console.log(null == undefined); //true console.log(undefined == 0); //false console.log(null == 0); //false console.log(undefined == undefined); //true console.log(null == null); //true
(4) NaN的比较
若是有一个操做数是NaN,则相等操做符返回 false; 两个操做数都是NaN,相等操做符也返回 false, NaN不与任何数相等, NaN不等于NaN
console.log(NaN == 0); //false console.log(NaN == NaN); //false
(5) 两个对象的比较
若是两个操做数都是对象,则比较它们是否是同一个对象。
① 若是两个操做数都指向同一个对象,则相等操做符返回 true;不然, 返回false
② 对于引用类型的数据,比较的是地址
console.log([] == []); //false console.log({} == {}); //false let a = []; let b = a; console.log(a == b); //true
3.多益笔试题
console.log('' == 0); //true 空串转为数字为0 console.log([] == 0); //true []调用toString()返回空串,再转为数字为0 console.log({} == 0); //false {}调用toString()返回[object Object],再转为数字为NaN
4.很绕的一题
(刚刚原本写了很详细的解析,没保存,此次不想再写了。)
关键在于:
!可将变量转换成boolean类型,null、undefined、NaN以及空字符串('')取反都为true,其他都为false。
{}调用toString()返回[object Object],再转为数字为NaN
console.log([] == ![]); //true console.log(![]); //false 至关于 console.log([] == 0); //true console.log({} == !{}); //false console.log(!{}); //false 至关于 console.log({} == 0); //false
(相比起来,全等运算符就没有那么多条条框框了,相等运算符整理到吐血)
(1)若是类型不一样,就必定不相等
(2)若是两个都是数值,而且是同一个值,那么相等;若是其中至少一个是NaN,那么不相等。(判断一个值是不是NaN,只能使用isNaN( ) 来判断)
(3)若是两个都是字符串,每一个位置的字符都同样,那么相等,不然不相等。
(4)若是两个值都是true,或者两个值都是false,那么相等
(5)若是两个值都引用同一个对象或是函数,那么相等,不然不相等
(6)若是两个值都是null,或者两个值都是undefined,那么相等
1.将非数值转换为数值类型的函数
Number()
:Number(mix),能够用于任何数据类型,该函数先将mix的数据类型转换为number类型,而后再将mix的值转换为数值。parseInt()
:将字符串转换为数值,不遵循四舍五入。这里的string必须是数字类型的开头字符串,一直遍历到非数值的那个字符才中止。若不是数字开头,则会显示NaN.parseFloat()
:将string转换为浮点数。从数字位开始看,直到非数字位结束,用法与parseInt(string)一致。2.将其它类型的数据转换为字符串类型的函数
String(mix)
:将mix转换成字符串类型。该函数能够将任何数据类型的值转换为字符串。toString()
:demo.toString()
将demo转换成字符串类型。demo不能是null undefined3.将值转换成布尔值类型Boolean()
方法把undefined、null、-0、+0、NaN、''(空字符串)六个值的转化为false,其余的值所有为true。
隐式类型的转换是系统进行运算时自动进行的,可是调用的方法都是显式类型转换的方法。
1.递增和递减操做符
不只适用于整数,还能够用于字符串、布尔值、浮点数值和对象。
即先将变量经过Number()
转换成number的数据类型,而后再进行递增、递减操做。
2.正负号
不只适用于整数,还能够用于字符串、布尔值、浮点数值和对象。
将变量经过Number()
转换成number的数据类型。
3.isNaN(变量)
执行过程为:即先将变量经过Number()
转换,再进行isNaN()
判断 。
4.加号
加法有两个做用。
5.- * / % (减号,乘号,除号,取余)
运算时把数据转换成number类型后,再进行运算。
6.&& || ! (与或非运算)
将运算符两边的值转换成经过Boolean()
函数转换成布尔类型,而后再进行运算。
不一样的是:&& || 返回的是比较后自身的原值,而 !运算返回的是布尔值.
7.< > <= >= == != 比较运算符
当数字和字符串比较大小时,会隐示将字符串转换成number类型进行比较。
而当字符串和字符串比较大小时,则比较的是ascii码的大小。最后返回的则是布尔值
1.
var str = 1 + 2 + 'abc'; console.log(str); //3abc
2.
var a; var b = a * 0; //console.log(b); //NaN //console.log(b === b); //false if(b === b){ console.log(b * 2 + "2" - 0 +4) }else{ console.log(!b * 2 + "2" - 0 +4) } //26
3.
var a = 1; //console.log(a); //1 var b = a * 0; //console.log(b); //0 if(b === b){ console.log(b * 2 + "2" -0 + 4) }else{ console.log(!b * 2 + "2" - 0 +4) } //6
4.涉及精度问题
var a = 1.0 - 0.9; if(a == 0.1){ console.log(true); } else{ console.log(false); } // false var b = 0.8 - 0.7; if(a == b){ console.log(true); }else{ console.log(false); } // false
本文参考连接:
toString()方法的讨论参考到了这篇:
https://www.cnblogs.com/xiaoh...
==&===的比较参考了这两篇:
http://javascript.ruanyifeng.com/grammar/operator.html#toc6
https://blog.csdn.net/magic_xiang/article/details/83686224
参考图片来自:博主:cc_ccc