这篇博客主要包括 数据类型 、 深拷贝 & 浅拷贝 、 数据类型的转换 、toString() 方法判断数据,如有错误,欢迎指正。
因为上次金山面试问了巨多这一块的内容,所以做个总结,零碎的知识点很多。这篇本来是上周先发在掘金的,但是掘金的排版器没有思否用着顺手,以后还是在这里更。。。(唉出场顺序太重要了,我爱思否)
数据类型
null 是对象类型还是基本数据类
1. 基本数据类型有 number,string,boolean,null,undefined,symbol(ES6 新增的),也称 原始数据类型。
2.JS 有 原始值类型 和引用值类型
2.1 原始值类型里面存储的都是值,原始值类型是无法改变的。
2.2 引用值类型指的是由多个值构成的对象。
let str = "hello";
str[0] = "z"; // 无法修改
一般情况下声明的变量是对象类型的话,会在栈内存中存放着引用地址,该地址会指向堆内存中的内容。
3.JS 内存分为堆内存和栈内存,栈内存保存的都是有固定大小、空间的内容。堆内存中存储的都是不固定的内容。
- 字符串是个特例,字符串具有不变性,字符串存储在栈内存中。
4. 二者区别
4.1 原始值类型保存在栈内存中,可以按值直接访问。
值与值之间是独立存在的,修改一个变量不会影响到其他变量。
var a = 10;
var b = a; // 将 a 的值赋给 b
b = 20;
console.log(a); // 10
console.log(b); // 20
① 基本数据类型赋值过程:
4.2 引用值类型存放在堆内存中,按照引用访问。
- 每新建一个新的对象,就会在堆内存中开辟一块新的空间
-
如果两个变量保存的是同一个对象引用,当通过一个变量修改属性时,另外一个也会受到影响。
var obj = new Object(); obj.name = "孙悟空"; var obj2 = obj; obj2.name = "猪八戒"; console.log(obj.name); // 猪八戒 console.log(obj2.name); // 猪八戒
② 引用数据类型赋值过程:
5. 如果两个对象一模一样,但也还是两个对象
- 当比较两个基本数据类型的值时,就是比较数值
- 比较两个引用数据类型时,比较的是对象的内存地址,对象相同,但地址不同,会返回 false
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 注意:
- Number()无法转换“数字 + 字母”组合,会转换为 NaN,
- undefined 也转换为 NaN
let str = Number('123');
console.log(str); //123
console.log(typeof str); //number
1.2 转换规则
- 纯数字字符串 –> 数字
- 字符串中有非数字内容 –> NaN
- undefined –> NaN
- 空字符串 / 空格 –> 0
- false –> 0
- Null –> 0
- true –> 1
2.数学运算符中的“+”、“-”
2.1 注意:
- “+”、“-”都可以将其他类型转换为数值类型,但是“-”会改变数值的正负性
- “+”、“-”底层上调用了 Number()函数
- “+”、“-”无法转换“数字 + 字母”组合
- 任何值做“-”、“*”、“/”运算都会自动转换为 Number 类型
let str = "123";
let num = +str;
console.log(num); //123
console.log(typeof num); //number
3.parseInt(字符串)和 parseFloat(字符串)
3.1 注意:
- parseInt()和 parseFloat()都会从左至右提取数值,一旦遇到非数值就会停止,返回 NaN
- parseInt()和 parseFloat()都会将传入的数据先转为 string 类型,再操作
let res = true;
// let res = "true";
let num = parseInt(res); // 把 true 当做字符串处理,没有遇到数字所以返回 NaN
console.log(num); //NaN
其他类型 —> 字符串类型
1.toString()
Number、Boolean 类型可调用 toString()转换为 String 类型
格式:变量名称.toString()
注意:
- toString()是对拷贝的数据进行转换,因此不会影响原有的数据
- 不能使用常量直接调用 toString()方法
- null 和 undefined 不可以调用 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 变量)
注意:
- String(变量 or 常量)可以转换常量,因为是根据传入的值重新生成一个新的值,并不会修改原有的值
- 常量可以直接使用 String()方法
- String()可以用来转换 null,undefined
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 常量)
注意:
- 只要字符串中有内容就会转换为 true,只要字符串的没有内容才会转换 false
- NaN、0 会转换为 false
- undefined、null 会转换为 false
总结:
空字符串 /0/NaN/undefined/null 会转换成 false
toString 方法一些讨论
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(","));
本文参考链接:
https://www.cnblogs.com/xiaoh…
参考图片来自:
博主:cc_ccc