JavaScript中的数据类型-前端学习笔记(一)

此篇文章为本人学习过程中总结的相关笔记,若有错误或不恰当之处,欢迎指正。

数据类型

JavaScript是一门弱类型的脚本语言,拥有动态类型。在程序运行过程中,类型会被自动确定,同时还可能伴随着类型隐式转换,所以在JavaScript中可以使用一个变量保存不同类型的数据。

JavaScript中的数据类型

ECMAScript定义了7中数据类型:

  • 原始类型(值类型):
    • Number
    • String
    • Boolean
    • Null
    • Undefined
    • Symbol
  • 引用类型:
    • Object

原始类型的值称为原始值,要注意原始值都是不可改变的,我们对原始类型的变量重新赋值时,是将变量指向了新的字符串的地址,而不是改变旧的字符串的值。

引用类型包括Object类及其所有的子类。JavaScript里的任何非原始类型都是对象(如Array、Function等),而且被存放在变量内。

JavaScript中的类型判断

在JavaScript中,判断类型一般用到的是 typeof 和 instanceof

typeof

使用typeof判断类型时,我们会得到7种结果

typeof 1;   // number
typeof new Number(1);   // object
typeof new String('');  // object
typeof '';  // string
typeof true;    // boolean
typeof Symbol('symbol');    // symbol
typeof undefined;    // undefined(Undefined类型只有一个特殊的值undefined)
typeof null;    // object(Null只有一个值null,但typeof null返回的是object, null可以看做空引用)
typeof {};  // object(Object的子类也是返回object)
typeof [];  // object
typeof new Set();  // object
typeof new Date();  // object
typeof function(){};    // function(Function类型的返回function而不是object)
复制代码
instanceof

instanceof运算符通过原型链判断一个对象是否为一个构造函数的实例。从一个实例对象开始向上查找原型链,直到Object.prototype,如果找到返回true,否则返回false。

当实例使用instanceof运算符时,会调用原型链上构造函数的Symbol.hasInstance方法。如obj instanceof Obj;会调用Obj[Symbol.hasIntance](obj);

class Klass {}
let obj = new Klass();
obj instanceof Klass;  // true
Klass[Symbol.hasInstance](obj);    // true
复制代码

再借用阮一峰老师的一个栗子:传送门

class Klass {
    static [Symbol.hasInstance](obj) {
        console.log(Number(obj));
    	return Number(obj) % 2 === 0;
    }
}

1 instanceof Klass;    // 1 false
2 instanceof Klass;    // 2 true
new Klass() instanceof Klass;  // NaN false
复制代码

上面的例子中,因为Klass类的Symbol.hasInstance方法被重写,所以产生了上面的结果。

下面是原始数据类型使用instance运算符的结果。

new Number(1) instanceof Number;    // true
new Number(NaN) instanceof Number;  // true
1 instanceof Number;    // false(数字字面量无原型链)
NaN instanceof Number;  // false
NaN === NaN;    // false
new String('') instanceof String;  // true
'' instanceof String;   // false(字符串字面量无原型链)
true instanceof Boolean;    // false
new Boolean(true) instanceof Boolean;   // true
null instanceof Object; //  false(null没有__proto__,无法进行原型链查找,Null也不是一个构造函数)
undefined instanceof Object; // false(同上)
Symbol(1) instanceof Symbol;    // false(Symbol无法实例化)
复制代码

下面再来看看引用类型的结果

class Klass {}
class Klass {}
let obj = new Klass();
obj instanceof Klass;  // true
obj.__proto__ = {}; // 通过修改实例__proto__的引用,使原型链断开
obj instanceof Klass;  // false
obj instanceof Object;  // true
new Array() instanceof Object;    // true
new Function() instanceof Object;   // true
复制代码

并非万物皆对象

到这里,再回头说一下上面说到的JavaScript的引用类型皆是对象。初学时,很多人都说,JavaScript中万物皆是对象,但实际上不是的,应该是JavaScript中非原始类型皆是对象。下面来看一下对象与非对象的区别。

instanceof返回false

这里已经说明原始类型不是对象了

1 instanceof Object;    // false
'' instanceof Object;    // false
复制代码
基本类型不存在属性
let number = 1;
number.prop = 'prop';
number.prop;    // undefined
复制代码
引用方式不同

将基本类型赋值给变量时,每次都是在内存中开辟一块空间,然后把内存地址保存在变量中,不会出现多个变量引用同一内存地址。

而引用类型进行赋值时,是将该对象的内存地址复制给新的变量,多个变量引用的是同一内存地址。

let number1 = 1024;
let number2 = number1;
++number1;   // 1025
number2;    // 1024
复制代码

那么问题来了,以下几个问题该怎么解释呢?

  • typeof null;    // object
    复制代码

    null解释为空对象引用,这是个历史遗留问题,详情不在这赘述了

  • let number = 1024;
    number.toString();   // 1024
    复制代码

    既然上面代码中number不是对象,为什么number调用Object.prototype上的方法成功了呢?这就需要了解一下基本包装类型(包装对象)了。那么包装对象和对象的区别是什么呢?

    最大的区别就是生命周期不同。一个对象被声明后直到被回收,一直都是一个对象。但是包装对象的生命周期是执行方法的过程。当保存原始类型的变量调用相应的方法时,解析引擎会封装一个包装对象,然后执行方法,执行完毕后销毁这个对象。大致流程如下

    let number = 1024;
    let string = number.toString();
    // 步骤如下
    // {
    //   let number = new Number(1024);
    //   let string = number.toString();
    //   number = null;
    // }
    复制代码
  • let number = 1024;
    number instanceof Number;    // false
    number.__proto__ === Number.prototype;   // true
    复制代码

    包装对象也解释了上述代码中,基本类型可以访问.__proto__并指向Number.prototype,instance却返回false的原因。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值