一、JavaScript 有几种类型的值?
Javascript 有两种数据类型,别离是根本数据类型和援用数据类型。其中根本数据类型包含 Undefined、Null、Boolean、Number、String、Symbol (ES6 新增,示意举世无双的值),而援用数据类型统称为 Object 对象,次要包含对象、数组和函数。接下来咱们别离看下两者的特点。
二、根本数据类型
1. 值是不可变的
var name = 'java';
name.toUpperCase(); // 输入 'JAVA'
console.log(name); // 输入 'java'
由此可得,根本数据类型的值是不可扭转的
2. 寄存在栈区
原始数据类型间接存储在栈 (stack) 中的简略数据段,占据空间小、大小固定,属于被频繁应用数据,所以放入栈中存储。
3. 值的比拟
var a = 1;
var b = true;
console.log(a == b); // true
console.log(a === b); // false
== : 只进行值的比拟, 会进行数据类型的转换。
=== : 不仅进行值得比拟,还要进行数据类型的比拟。
三、援用数据类型
1. 值是可变的
var a={age:20};a.age=21;console.log(a.age)//21
下面代码阐明援用类型能够领有属性和办法,并且是能够动静扭转的。
2. 同时保留在栈内存和堆内存
援用数据类型存储在堆 (heap) 中的对象, 占据空间大、大小不固定, 如果存储在栈中,将会影响程序运行的性能;援用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址。当解释器寻找援用值时,会首先检索其在栈中的地址,获得地址后从堆中取得实体。
3. 比拟是援用的比拟
当从一个变量向另一个变量赋援用类型的值时,同样也会将存储在变量中的对象的值复制一份放到为新变量调配的空间中。
var a={age:20};
var b=a;
b.age=21;
console.log(a.age==b.age)//true
下面咱们讲到根本类型和援用类型存储于内存的地位不同,援用类型存储在堆中的对象,与此同时,在栈中存储了指针,而这个指针指向正是堆中实体的起始地位。变量 a 初始化时,a 指针指向对象 {age:20} 的地址,a 赋值给 b 后,b 又指向该对象 {age:20} 的地址,这两个变量指向了同一个对象。因而,扭转其中任何一个变量,都会相互影响。
此时,如果勾销某一个变量对于原对象的援用,不会影响到另一个变量。
var a={age:20};
var b=a;
a = 1;
b // {age:20}
下面代码中,a 和 b 指向同一个对象,而后 a 的值变为 1,这时不会对 b 产生影响,b 还是指向原来的那个对象。
四、测验数据类型
1.typeof
typeof 返回一个示意数据类型的字符串,返回后果包含:number、boolean、string、symbol、object、undefined、function 等 7 种数据类型,但不能判断 null、array 等
typeof Symbol(); // symbol 无效
typeof ''; // string 无效
typeof 1; // number 无效
typeof true; //boolean 无效
typeof undefined; //undefined 无效
typeof new Function(); // function 无效
typeof null; //object 有效
typeof [] ; //object 有效
typeof new Date(); //object 有效
typeof new RegExp(); //object 有效
数组和对象返回的都是 object,这时就须要应用 instanceof 来判断
2.instanceof
instanceof 是用来判断 A 是否为 B 的实例,表达式为:A instanceof B,如果 A 是 B 的实例,则返回 true, 否则返回 false。instanceof 运算符用来测试一个对象在其原型链中是否存在一个构造函数的 prototype 属性。
[] instanceof Array; //true
{} instanceof Object;//true
new Date() instanceof Date;//true
new RegExp() instanceof RegExp//true
对于数组的类型判断,还能够用 ES6 新增Array.isArray()
Array.isArray([]); // true
instanceof 三大弊病:
- 对于根本数据类型来说,字面量形式创立进去的后果和实例形式创立的是有肯定的区别的
console.log(1 instanceof Number)//false
console.log(new Number(1) instanceof Number)//true
从严格意义上来讲,只有实例创立进去的后果才是规范的对象数据类型值,也是规范的 Number 这个类的一个实例;对于字面量形式创立进去的后果是根本的数据类型值,不是谨严的实例,然而因为 JS 的涣散特点,导致了能够应用 Number.prototype 上提供的办法。
- 只有在以后实例的原型链上,咱们用其检测进去的后果都是 true。在类的原型继承中,咱们最初检测进去的后果未必精确。
var arr = [1, 2, 3];
console.log(arr instanceof Array) // true
console.log(arr instanceof Object); // true
function fn(){}
console.log(fn instanceof Function)// true
console.log(fn instanceof Object)// true
- 不能检测 null 和 undefined
对于非凡的数据类型 null 和 undefined,他们的所属类是 Null 和 Undefined,然而浏览器把这两个类爱护起来了,不容许咱们在里面拜访应用。
3.constructor
constructor 作用和 instanceof 十分类似。但 constructor 检测 Object 与 instanceof 不一样,还能够解决根本数据类型的检测。
var aa=[1,2];
console.log(aa.constructor===Array);//true
console.log(aa.constructor===RegExp);//false
console.log((1).constructor===Number);//true
var reg=/^$/;
console.log(reg.constructor===RegExp);//true
console.log(reg.constructor===Object);//false
constructor 两大弊病:
- null 和 undefined 是有效的对象,因而是不会有 constructor 存在的,这两种类型的数据须要通过其余形式来判断。
- 函数的 constructor 是不稳固的,这个次要体现在把类的原型进行重写,在重写的过程中很有可能呈现把之前的 constructor 给笼罩了,这样检测进去的后果就是不精确的
function Fn(){}
Fn.prototype = new Array()
var f = new Fn
console.log(f.constructor)//Array
4.Object.prototype.toString.call()
Object.prototype.toString.call() 最精确最罕用的形式。首先获取 Object 原型上的 toString 办法,让办法执行,让 toString 办法中的 this 指向第一个参数的值。
对于 toString 重要补充阐明:
- 本意是转换为字符串,然而某些 toString 办法不仅仅是转换为字符串
- 对于 Number、String,Boolean,Array,RegExp、Date、Function 原型上的 toString 办法都是把以后的数据类型转换为字符串的类型(它们的作用仅仅是用来转换为字符串的)
- Object 上的 toString 并不是用来转换为字符串的。
Object 上的 toString 它的作用是返回以后办法执行的主体(办法中的 this)所属类的详细信息即 ”[object Object]”, 其中第一个 object 代表以后实例是对象数据类型的(这个是固定死的),第二个 Object 代表的是 this 所属的类是 Object。
Object.prototype.toString.call('') ; // [object String]
Object.prototype.toString.call(1) ; // [object Number]
Object.prototype.toString.call(true) ; // [object Boolean]
Object.prototype.toString.call(undefined) ; // [object Undefined]
Object.prototype.toString.call(null) ; // [object Null]
Object.prototype.toString.call(new Function()) ; // [object Function]
Object.prototype.toString.call(new Date()) ; // [object Date]
Object.prototype.toString.call([]) ; // [object Array]
Object.prototype.toString.call(new RegExp()) ; // [object RegExp]
Object.prototype.toString.call(new Error()) ; // [object Error]
Object.prototype.toString.call(document) ; // [object HTMLDocument]
Object.prototype.toString.call(window) ; //[object global] window 是全局对象 global 的援用