让前端飞

JS基础系列(一)JS数据类型

2020-02-15  本文已影响0人  郁南

原生js数据类型、存储以及拷贝

1、类型

const a =null; // null
const b = undefined; // undefined
const c = 123; // number
const d = `hello world ` // string
const e = true; // boolean  
const obj = {name:’jack’};// Object
const arr = [1,2,3]; // Array
const fn = function(){console.log(’这是一个函数’)} // Function

2、存储

引用数据类型都是保存在堆内存中的,然后再在栈内存中保存一个对堆内存中实际对象的引用,所以一般js中对引用数据类型的直接操作都是操作对象的引用,而不是操作实际对象。

3、拷贝

4、拷贝方式

const a = 123; const b = a;a = 456;console.log(a,b); //456 123
const obj = {a:123}; 
const copyA = obj; 
const copyB = deepClone(obj); 
obj.a = 456;
console.log(copyA, copyB); // {a:456} {a:123}

看上面的输出,就很容易知道为啥要实现深拷贝了。
下面看实现深拷贝思路:

//使用 toString() 检测对象类型
//可以通过 toString() 来获取每个对象的类型。为了每个对象都能通过 //Object.prototype.toString() 来检测,需要以 Function.prototype.call() 或者 Function.prototype.apply() 的形式来调用,传递要检查的对象作为第一个参数,称为 thisArg。
var toString = Object.prototype.toString;

toString.call(new Date); // [object Date]
toString.call(new String); // [object String]
toString.call(Math); // [object Math]

//Since JavaScript 1.8.5
toString.call(undefined); // [object Undefined]
toString.call(null); // [object Null]
function getType(obj) {
    //tostring会返回对应不同的标签的构造函数
    var toString = Object.prototype.toString;
    var map = {
        '[object Boolean]': 'boolean',
        '[object Number]': 'number',
        '[object String]': 'string',
        '[object Function]': 'function',
        ‘[object Array]’: ‘array’,
        ‘[object Date]': 'date',
        '[object RegExp]': 'regExp',
        '[object Undefined]': 'undefined',
        '[object Null]': 'null',
        '[object Object]’: ‘object’
    };
    if (obj instanceof Element) {
        return ‘element’;
    }
    return map[toString.call(obj)];
}

通过这个函数,我们可以获取变量的最终类型。

function deepClone(data) {
    var type = getType(data);
    var obj;
    if (type === ‘array’) {
        obj = [];
    } else if (type === 'object') {
        obj = {};
    } else {
        //不再具有下一层次
        return data;
    }
    if (type === 'array') {
        for (var I = 0, len = data.length; I < len; i++) {
            obj.push(deepClone(data[i]));
        }
    } else if (type === 'object') {
        for (var key in data) {
            obj[key] = deepClone(data[key]);
        }
    }
    return obj;
}

思路是:在深拷贝函数中,先获取数据类型,并且声明一个变量,开辟新的内存空间,然后根据不同的类型赋值给内部的新对象:如果是简单类型,直接返回该数据,完成拷贝;如果不是,针对ObjectArray递归获取对应的值或者键值对并复制给内建变量,最终完成深拷贝。

当然,在ES5+中实现拷贝还是有别的方式,比如常用的JSON.parse(JSON.stringify(obj));扩展运算符、Object.assign()都可以实现浅拷贝,具体本文不做深入讨论。

最后总结一下基础数据类型和引用数据类型的区别:

  1. 堆比栈大,栈比堆速度快。
  2. 基础数据类型比较稳定,而且相对来说占用的内存小。
  3. 引用数据类型大小是动态的,而且是无限的。
  4. 堆内存是无序存储,可以根据引用直接获取。

个人理解,不足或者有错之处希望可以帮忙指出,感谢🙏

上一篇 下一篇

猜你喜欢

热点阅读