JS基本数据类型以及深浅拷贝

看文章前请先看这里!!第一次在CSDN发布自己的内容,排版不好请多包含!希望用两句话说明白的问题不多讲废话,努力做到写的都是干货,让每一个看的人不浪费时间,同时也让和我一样的小白能看懂!每一次写都是很用心的写!

文章目录

  • 前言
  • 一、JavaScript有几种数据类型?
  • 二、判断数据类型的方法
    • 1.typeof
    • 2.instanceof
    • 3.constructor
    • 4.Object.prototype.toString.call()
    • 5.比较一下四种方法优缺点!!
  • 三,深浅拷贝
    • 浅拷贝
    • 浅拷贝的方法
    • 深拷贝
    • 深拷贝方法
    • 实现一个深拷贝函数
  • 总结


前言

今天复习一下有关数据类型的内容

一、JavaScript有几种数据类型?

在JavaScript中有两种数据类型,分为基本数据类型引用数据类型
基本数据类型中包括:String,Number,Undefined,Null,Boolean,Symbol
引用数据类型中包括:Object,Funtion,Array,Error,Set,Map等等…

两者主要区别在于:
基本数据类型存储的是值,引用数据类型中存储的是地址。当创建一个引用类型的时候,计算机会在内存中帮我们开辟一个空间存放,这个空间有一个地址。

二、判断数据类型的方法

常用判断数据类型的方法有四种:typeof,instanceof,constructor,Object.prototype.toString.call()

1.typeof

typeof:可以对基本数据类型(除Null)做出准确判断,对于引用类型(除Function)都无法做出准确判断,返回均为Object,因为所有对象的原型链最终都指向了Object。

typeof返回一个表示数据类型的字符串,返回结果包括了:number,boolean,string,object,function,undefined,symbol七种数据类型。

typeof null返回的是Object,typeof function返回 function

2.instanceof

instanceof运算符用于检测构造函数的prototype属性是否出现于某个实例对象的原型链上。 ——MDN

代码如下(示例):

var str = '放牛大户'
console.log(str instanceof String) // false
var bool = true
console.log(bool instanceof Boolean) // false
var num = 123
console.log(num instanceof Boolean) // false
var nul = null
console.log(nul instanceof Object) // false
var und = undefined
console.log(und instanceof Object) // false
// 从上面的运行结果来看,基本数据类型是没办法检测出来的

// 但是通过构造函数创建的基本数据类型是可以检测出来的,看下面代码
var num = new Number(123)
console.log(num instanceof Number) // true
var str = new String('abc')
console.log(str instanceof String) // true
var boolean = new Boolean(true)
console.log(boolean instanceof Boolean) // true
// 剩下的自己试一下,通过构造函数创建的基本数据类型是可以检测出来的

// 对于引用类型也是可以检测出来的
var oDate = new Date();
console.log(oDate instanceof Date) // true
var json = {
     };
console.log(json instanceof Object) // true
var arr = [];
console.log(arr instanceof Array) // true
var reg = /a/;
console.log(reg instanceof RegExp) // true
var fun = function(){
     };
console.log(fun instanceof Function) // true
var error = new Error();
console.log(error instanceof Error) // true

这里有人说instanceof无法判断基本数据类型,根据定义我理解的是只要是通过构造函数创建的,无论是基本数据类型还是引用数据类型都是可以检测出的,欢迎打脸!

3.constructor

constructor:查看对象对应的构造函数
这种方式可以判断(除null和undefined之外)所有数据类型。因为undefined和null是无效对象,没有constructor存在。

代码如下(示例):

// 这里就不都一一列举啦!
var str = '放牛大户'
console.log(str.constructor == String) // true
var bool = true
console.log(boor.constructor ==Boolean) // true
var arr = [];
console.log(arr.constructor == Array) //true
var fun = function() {
     };
console.log(fun.constructor == Function) //true
// 下面这两个会报错哦!
// var nul = null;
// console.log(nul.constructor == Object) //报错
//var und = undefined;
//console.log(und.constructor == Object) //报错

constructor是不保险的,因为constructor属性是可以被修改的,会导致检测出的结果不正确

function A() {
     }
function B() {
     }
// 这里我们声明两个构造函数
A.prototype.constructor = B
// 修改一下A构造函数的指向
console.log(A.constructor == A) // false

4.Object.prototype.toString.call()

Object.prototype.toString.call():该方法是通过子类在内部借用Object中提供的toString()方法,默认返回其调用者的具体类型。

格式为[object xxx],xxx是具体的数据类型。

代码如下(示例):

var str = '放牛大户';
console.log(Object.prototype.toString.call(str));//[object String]
var bool = true;
console.log(Object.prototype.toString.call(bool))//[object Boolean]
var num = 123;
console.log(Object.prototype.toString.call(num));//[object Number]
var nul = null;
console.log(Object.prototype.toString.call(nul));//[object Null]
var und = undefined;
console.log(Object.prototype.toString.call(und));//[object Undefined]
var oDate = new Date();
console.log(Object.prototype.toString.call(oDate));//[object Date]
var json = {
     };
console.log(Object.prototype.toString.call(json));//[object Object]
var arr = [];
console.log(Object.prototype.toString.call(arr));//[object Array]
var reg = /a/;
console.log(Object.prototype.toString.call(reg));//[object RegExp]
var fun = function(){
     };
console.log(Object.prototype.toString.call(fun));//[object Function]
var error = new Error();
console.log(Object.prototype.toString.call(error));//[object Error]

5.比较一下四种方法优缺点!!

JS基本数据类型以及深浅拷贝_第1张图片


我想上面那部分内容对你来说都是开胃菜了,铺垫完基本数据类型和引用数据类型,今天的最重要的部分要来了!深浅拷贝冲呀!!!你点目录跳到这里会不会看不到我这部分内容,我想和你互动一下

三,深浅拷贝

在介绍基本数据类型和引用数据类型的区别时说,基本数据类型是按值访问的,当变量复制基本类型后,这两个变量是完全独立的。即使修改第一个变量,也不会影响到第二个变量!!(不信你试一下?要不我写段代码吧)

代码如下(示例):

var str1 = 'a'
var str2 = str1
str2 = 'b'
console.log(str1)  // a
console.log(str2) // b

但对于引用数据类型,当变量复制引用类型后,和基本类型一样的是都将变量值复制到新的变量上。但是它是一个指针指向存储在堆内存中的对象,这里我上个图看一下。

这图好不容易找到的呢,没办法谁叫我不会画呢,先谢谢原博主了,因为我没经过人家同意用的!!

JS基本数据类型以及深浅拷贝_第2张图片

浅拷贝

浅拷贝:创建一个新的对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值;如果属性是内存地址(引用类型),拷贝的就是内存地址,因此如果其中一个对象改变了这个地址,就会影响到另一个对象。即默认拷贝构造函数只是对对象进行浅拷贝复制,只复制资源而不复制空间——百度百科

浅拷贝的方法

1.Object.assign(target,…sources):第一个参数是拷贝目标,剩下的参数是拷贝的源对象。返回值:拷贝目标

注意:

  1. 不会拷贝对象继承的属性
  2. 如果目标对象中和源对象中有相同属性,则源对象会覆盖目标对象的属性

代码如下(示例):

const target = {
      a: 1, b: 2 };
const source = {
      b: 4, c: 5 };
const returnedTarget = Object.assign(target, source);
console.log(target);// expected output: Object { a: 1, b: 4, c: 5 }
console.log(returnedTarget);// expected output: Object { a: 1, b: 4, c: 5 }

Object.assign():这种方法实现了单层深拷贝当对象只有一层属性是为深拷贝,对深层(对象中还有对象)还是浅拷贝

代码如下(示例):

 let obj1 = {
     
        a: 1,
        b: {
     c: {
     d: 0 } }
    };
let obj2 = Object.assign({
     }, obj1)
let obj3 = JSON.parse(JSON.stringify(obj1)); // 这是深拷贝方法,在这里我们做一个对比

// 第一层都是深拷贝时,修改拷贝源对象也就是obj时,对其他两个对象并没有影响
obj1.a = 2; 
console.log(obj1.a) //2
console.log(obj2.a) //1
console.log(obj3.a) //1

// 深层时为浅拷贝,再修改源对象时,对obj2产生了影响
obj1.b.c.d = 1; 
console.log(obj1.b.c.d); //1
console.log(obj2.b.c.d); //1
console.log(obj3.b.c.d); //0

2.扩展运算符:利用扩展运算符可以在构造字面量对象时,进行克隆或属性拷贝。和Object.assign有着同样的问题,当对象只有一层是为深拷贝,如果对象中有对象的话为浅拷贝。

代码如下(示例):

var obj = {
     a:1,b:{
     c:1}}
var obj2 = {
     ...obj};
obj.a=2;
console.log(obj); //{a:2,b:{c:1}}
console.log(obj2); //{a:1,b:{c:1}}
obj.b.c = 2;
console.log(obj); //{a:2,b:{c:2}}
console.log(obj2); //{a:1,b:{c:2}}

深拷贝

深拷贝:将一个对象内存完整的拷贝一份出来,从内存中开辟一个新的区域存放新对象,且修改新对象不会影响原对象。

深拷贝方法

通过JSON.stringify() 和 JSON.parse()实现深拷贝

  1. JSON.stringify():把一个对象序列化成为一个JSON字符串
  2. JSON.parse():将JSON字符串反序列化为一个对象

代码如下(示例):

var obj1 = {
     
	a:1,
	b:[1,2,3]
}
var str = JSON.stringify(obj1)
var obj2 = JSON.parse(str)
console.log(obj2) // {a:1,b:[1,2,3]}
obj1.a = 2
obbj1.b.push(4)
console.log(obj1) // {a:2,b:[1,2,3,4]}
console.log(obj2) // {a:1,b:[1,2,3]}

实现一个深拷贝函数

这里封装了一个deepClone函数。for in遍历传入参数的值,如果是引用类型,再次调用deepClone函数,并且传入第一次调用deepClone参数的值作为第二次调用deepClone的参数,如果不是引用类型直接复制。

代码如下(示例):

var obj1 = {
     
	a:{
     
		b:1
	}
}
function deepClone(obj1){
     
	// 在堆内存中创建一个新对象
	var cloneObj = {
     };
	// 遍历参数的属性
	for (var key in obj) {
     
		// 判断属性类型是否为obj,如果是需要再次循环遍历该对象的属性
		if(typeof obj[key] === 'object'){
     
			cloneObj[key] = deepClone(obj[key])
		}else{
     
			cloneObj[key] = obj[key]
		}
	}
	return cloneObj
}


总结

今天所有的内容完事啦!如有帮助麻烦鼓励一下哦!

你可能感兴趣的:(前端面试准备,前端,javascript)