js中的数据类型

1. 基本数据类型和复杂数据类型

  • 基本类型:undefinednullboolstringnumbersymbol(ES6新增)。

虽然 typeof null 返回的值是 object,但是null不是对象,而是基本数据类型的一种。这是一个历史遗留问题,JS 的最初版本中使用的是 32 位系统,为了性能考虑使用低位存储变量的类型信息,000 开头代表是对象,null 表示为全零,所以将它错误的判断为 object

基本数据类型存储在栈内存,存储的是值。

  • 复杂数据类型:ObjectArrayDatefunction

复杂数据类型的值存储在堆内存,地址(指向堆中的值)存储在栈内存。当我们把对象赋值给另外一个变量的时候,复制的是地址,指向同一块内存空间,当其中一个对象改变时,另一个对象也会变化。

[1] == [1] // false
{name:1} == {name:1}  // false

因为引用类型值比较的是地址,这两个对象字面量指向不同的引用地址,所以为false。

2. 判断方法

  • typeof

typeof 能够正确的判断基本数据类型,但是除了 nulltypeof null输出的是对象。但是对象来说,typeof 不能正确的判断其类型, typeof 一个函数可以输出 ‘function’,而除此之外,输出的全是 object,这种情况下,我们无法准确的知道对象的类型。

  • instanceof

instanceof可以准确的判断复杂数据类型,但是不能正确判断基本数据类型。
instanceof 是通过原型链判断的,A instanceof B, 在A的原型链中层层查找,是否有原型等于B.prototype,如果一直找到A的原型链的顶端(null;即Object.__proto__),仍然不等于B.prototype,那么返回false,否则返回true

instanceof的一个实现:

//L instance_of R
function instance_of(L, R) {
    var O = R.prototype;  //取R的显式原型
    L = L.__proto__; //取L的隐式原型
    while(true) {
        if(L===null) {  //已经找到顶层
            return false;
        } else if(O===L) {  //当O严格等于L时,返回true
            return true;
        }
        L = L.__proto__; //继续向上一层原型链查找
    }
}

console.log(instance_of([], Array))  //true
  • Object.prototype.toString.call(obj) === ‘[Object ’ + type + ‘]’

用该方法检测出的nullNull类型:

var a = Symbol();
var b = 23;
console.log(Object.prototype.toString.call(a));  // [object Symbol]
console.log(Object.prototype.toString.call(null));  // [object Null]
console.log(Object.prototype.toString.call(undefined));  // [object Undefined]
console.log(Object.prototype.toString.call(b));  // [object Number]

如果想要了解Object.prototype.toString.call()的原理,可参考链接https://www.cnblogs.com/ziyunfei/archive/2012/11/05/2754156.html

3. 基本数据类型和复杂数据类型的区别为:

  • 内存的分配不同
    基本数据类型存储在栈中;
    复杂数据类型存储在堆中,栈中存储的变量,是指向堆中的引用地址。
  • 访问机制不同
    基本数据类型是按值访问;
    复杂数据类型按引用访问,JS不允许直接访问保存在堆内存中的对象,在访问一个对象时,首先得到的是这个对象在栈内存中的地址,然后再按照这个地址去获得这个对象中的值。
  • 复制变量时不同(a=b)
    基本数据类型:a=b;是将b中保存的原始值的副本赋值给新变量aab完全独立,互不影响;
    复杂数据类型:a=b;b保存的对象内存的引用地址赋值给了新变量aab指向了同一个堆内存地址,其中一个值发生了改变,另一个也会改变。
let b = {
    age: 10
}

let a = b;
a.age = 20;
console.log(b); //{ age: 20 }
  • 参数传递的不同(实参/形参)
    函数传参都是按值传递(栈中的存储的内容):基本数据类型,拷贝的是值;复杂数据类型,拷贝的是引用地址,具体细节参考链接:
    https://juejin.im/post/5a5cb80151882573385fb84d#comment
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值