一、直接量和变量
1、直接量
数值(10、20)、逻辑值(true、false)、字符串(“xx”)、null、undefined、对象(存放数据的一个容器)、函数(方法)。
2、变量
指向直接量或其他变量。
二、数据
1、原生数据类型:
只能存放一些直接量,包括:
数值(number):整数和小数(比如1和3.14)
字符串(string):字符组成的文本(比如”Hello World”)
布尔值(boolean):true(真)和false(假)两个特定值
undefined:表示“未定义”或不存在,即由于目前没有定义,所以此处暂时没有任何值
null:表示无值,即此处的值就是“无”的状态。
注:ES6中新增Symbol和BigInt类型。
(1)Symbol代表创建后独一无二且不可变的数据类型,主要为了解决可能出现的全局变量冲突问题。
(2)BigInt初期我们无法表示大于2{{53}}-1的数,BigInt数据类型提供了一种方法来表示大于2{{53}}-1的整数。BigInt可以表示任意大的整数,BigInt数据类型比Number类型支持更大的整数值。
2、引用数据类型:
(1)对象及创建方法
对象(object):各种值组成的集合,复合型数据类型
创建对象:
var happy = {
happy1 : "smile" ,
happy2 : "laugh"
};
最常用的创建对象的方式就是一个大括号,里面包括若干键值对,也就是上面代码中的happy1 : “smile”,其中happy1叫做键,smile叫做值。
与上面方法不同的是,还可以用下面的代码创建对象:
var happy = {};
happy.happy1 = "smile";
happy.happy2 = "laugh";
console.log(happy.happy3);
显然,console.log(happy.happy3)的值为undefined,因为happy对象中,happy3未定义。
(2)对象的取值
分两种情况:一种是已知对象的属性名,怎样访问其属性值;另一种是不知道对象的属性名称。
①对于已知对象的属性名的情况,可以用上面那种“.”的方式访问其值;
②对于不知道对象的属性名称的情况,可以用“[ ]”的方式访问,[]中允许写入变量或字符串。同时,“[ ]”也可以用于调用属性是动态变化的情况。
比如说:
var happy = {};
happy.happy1 = "smile";
happy.happy2 = "laugh";
var xx = "happy1";
console.log(happy[xx]);
console.log(happy["happy1"]);
相较来说,中括号的灵活性更大。
3、两种类型区别:
在于存储位置的不同
●原始数据类型直接存储在栈stack中的简单数据段,占据空间小、大小固定,属于被频繁使用数据,所以放入栈中存储;在数据结构中,栈中数据的存取方式为先进后出。
●引用数据类型存储在堆heap中的对象,占据空间大、大小不固定。如果存储在栈中,将会影响程序运行的性能;引用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址。当解释器寻找引用值时,会首先检索其在栈中的地址,取得地址后从堆中获得实体。 堆和栈的概念存在于数据结构和操作系统内存中,在数据结构中,堆是一个优先队列,是按优先级来进行排序的,优先级可以按照大 小来规定。 在操作系统中,内存被分为栈区和堆区:
●栈区内存由编译器自动分配释放,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。堆区内存一般由开发着分配释放,若开发者不释放,程序结束时可能由垃圾回收机制回收。
三、数据类型检测
1、typeof
其中数组、对象、null 都会被判断为 object
console.log(typeof 3); //number
console.log(typeof false); //boolean
console.log(typeof 'hello'); //string
console.log(typeof []); //object
console.log(typeof function(){}); //function
console.log(typeof {}); //object
console.log(typeof undefined); //undefined
console.log(typeof null); //object
2、instanceof
instanceof 可以正确判断对象的类型,其内部运行机制是判断在其 原型链中能否找到该类型的原型。instanceof 只能正确判断引用数据类型,而不能判断基本数据类型。instanceof 运算符可以用来测试一个对象在其原型链中是否存在一个构造函数的 prototype 属性。
console.log(2 instanceof Number); //false
console.log([] instanceof Array); //true
3、constructor
constructor 有两个作用,一是判断数据的类型,二是对象实例通过 constrcutor 对象访问它的构造函数。
console.log((2).constructor === Number); //true
需要注意,如果创建一个对象 来改变它的原型,constructor 就不能用来判断数据类型了
function Wang(){};
Wang.prototype = new Array();
var w = new Wang();
console.log(w.constructor === Wang); //false
console.log(w.constructor === Array); //true
4、Object.prototype.toString.call()
Object.prototype.toString.call() 使用 Object 对象的原型方法 toString 来判断数据类型。
注:
同样是检测对象 obj 调用 toString 方法,obj.toString()的结果和 Object.prototype.toString.call(obj)的结果不一样,这是为什 么?
这是因为 toString 是 Object 的原型方法,而 Array、function 等类型作为 Object 的实例,都重写了 toString 方法。不同的对象类型调用 toString 方法时,根据原型链的知识,调用的是对应的重写之后的 toString 方法(function 类型返回内容为函数体的字符串,Array 类型返回元素组成的字符串…),而不会去调用 Object 上原型 toString 方法(返回对象的具体类型),所以采用 obj.toString() 不能得到其对象类型,只能将 obj 转换为字符串类型;因此,在想要 得到对象的具体类型时,应该调用 Object 原型上的 toString 方法。
四、null 和 undefined 区别
总的来说 null 和 undefined 都代表空,主要区别在于 undefined 表示尚未初始化的变量的值,而 null 表示该变量有意缺少对象指向。
undefined:这个变量从根本上就没有定义,隐藏式空值
null:这个值虽然定义了,但它并未指向任何内存中的对象,== 声明式空值==
undefined 在 JavaScript 中不是一个保留字,这意味着可以使用 undefined 来作为一个变量名,但是这样的做法是非常危险的,它会影响对 undefined 值的判断。我们可以通过一些方法获得安全的 undefined 值,比如说 void 0。 当对这两种类型使用 typeof 进行判断时,Null 类型化会返回 “object”,这是一个历史遗留的问题。当使用双等号对两种类型的 值进行比较时会返回 true,使用三个等号时会返回 false