JS中的数据类型可以这样分类:
原始数据类型: number, string ,boolean, undefined, null, symbol
-
基本类型(简单类型):
- 值类型: number((整数/小数/NaN));string,boolean
- 空类型:null,undefined
- 还有 symbol (ES6)
-
复杂类型(引用类型):object
基本数据类型
JavaScript 中共有 6 种基本数据类型:undefined、null、boolean、number、string、symbol (new in ES 6) 。
- 访问基本数据类型是按值访问的。
- 基本类型的值不可变
var str = "123HelloWorld321"; str.toUpperCase(); console.log(str.toUpperCase()); // 123HELLOWORLD321 console.log(str); // 123HelloWorld321
- 基本类型的比较是它们的值的比较
上面 a 和 b 的数据类型不同,但是也可以进行值的比较,这是因为在比较之前,自动进行了数据类型的 隐式转换。var a = 1; var b = '1'; console.log(a == b); // true console.log(a === b); // false
- 基本类型的变量存放在栈内存里
var a = 10; var b = a; b = 20; console.log(a); console.log(b);
b获取的是a值的一个副本,虽然两个变量的值相等,但是两个变量保存了两个不同的基本数据类型值。所以b值的改变不会影响a的值。
-
值类型作为函数的参数,传递的是值
function f1(x) { x=100; } var num1=10; f1(num1); //num1的值复制了一份给了x,然后 x被重新赋值为100, x的值变了,但是num1的值没有变, console.log(num1); // num1的值还是 10
引用数据类型
Object 类型,细分的话有:Object 类型、Array 类型、Date 类型、RegExp 类型、Function 类型等。
-
引用类型的值是按引用来访问的。
- 引用类型的值是可变的。
var obj = {name:"lmg"}; // 创建一个对象 obj.name = "xiaoming"; // 改变 name 属性的值 obj.age = 18; // 添加 age 属性 obj.sayHi = function(){ return this.name + " : " + this.age; }; // 添加 sayHi 方法 obj.sayHi();
- 引用类型的比较是引用的比较
var obj1 = {}; // 新建一个空对象 obj1 var obj2 = {}; // 新建一个空对象 obj2 console.log(obj1 == obj2); // false console.log(obj1 === obj2); // false
obj1 和 obj2 分别引用的是存放在堆内存中的2个不同的对象,故变量 obj1 和 obj2 的值(引用地址)也是不一样的。
- 引用类型的值是保存在堆内存中的对象
var a = {name:"percy"}; var b; b = a; a.name = "zyj"; console.log(b.name); // zyj b.age = 22; console.log(a.age); // 22 var c = { name: "zyj", age: 22 };
图解:
注:栈内存中保存了变量标识符和指向堆内存中该对象的指针。堆内存中保存了对象的内容。- 引用类型作为函数的参数,传递的是引用(地址)
var obj={ name:'xiaoming' }; function f2(obj2) { obj2.name='xiaohong'; } console.log(obj.name); //xiaoming f2(obj); //obj的地址复制一份给了obj2,地址相同,指向同一对象, 调用时name改成了xiaohong,xiaoming就被替换掉了, console.log(obj.name); // xiaohong
案例分析:
//案例1分析: 会画缓存图
var n1=10;
var n2=n1;
n1=20;
console.log(n1); //20
console.log(n2); //10
//案例2:
var n3=50;
function ff(n3) { // 这里的n3是形参, 实参与形参即使名字相同。也不是同一个变量
n3=60;
console.log(n3); //60
}
ff(n3); //注意:这里的n3是实参
console.log(n3); //这里是函数外的n3,为50, 函数里面的n3是没有关系的
//案例3:
var n4=55;
var n5=66;
function f_(n,n4) { //n,n4在函数内部是局部变量
n=100; //局部变量,它的传进来的值对应外面的n4, 55
n4=100; //局部变量,它的传进来的值对应外面的n5, 66
n5=100; //注意:!!隐式全局变量!!
console.log(n); // 100
console.log(n4); // 100
console.log(n5); // 100
}
f_(n4,n5);
console.log(n4); // 55, 这个是全局变量n4
console.log(n5);// 100,这个是函数中的隐式全局变量
console.log(n); // ReferenceError: n is not defined报错:这个是函数中的局部变量,访问不到
//案例4:
function Person(name,age,salary) { //自定义构造函数
this.name=name;
this.age=age;
this.salary=salary;
}
function fff(person) { //创建了普通的函数
person.name='ls'; //name修改了, 变成了ls
person=new Person('aa',18,10); //新创建的一个对象,person指向了这个对象, person 和p指向的对象不同了
}
var p = new Person('zs',18,1000);
console.log(p.name); //zs
fff(p); //函数调用,对象p的地址复制一份给person,所以他们指向同一个对象
console.log(p.name); //ls
数据类型的检测方法:typeof 与 instanceof
-
typeof: 主要用来检测一个变量是不是一个基本的数据类型,返回的是具体的数据类型。
var a; console.log(typeof a); //undefined 输出的这些类型都是小写的字符串 var b = null; console.log(typeof b); // object 注意 var c = 123; console.log(typeof c); // number var d = '123'; console.log(typeof d); // string var e = true; console.log(typeof e); // boolean var f = Symbol(); console.log(typeof f); // symbol var g = function () { console.log(g); }; console.log(typeof g); // function var h = []; console.log(typeof h); // object var i = {}; console.log(typeof i); // object var j = /123/g; console.log(typeof j); // object
-
instanceof:判断一个引用类型的变量具体是不是某种类型的对象,返回的是布尔值。
console.log(g instanceof Function); // true console.log(h instanceof Array); // true console.log(i instanceof Object); // true console.log(j instanceof RegExp); // true