? JS Type 原始数据类型
? 声明多个标量应该使用逗号
var a = 0, b //right
let a = 0, b //right
var a = 0; b //false
let a = 0; b //false
复制代码
? Basic Type
原始类型和引用类型的区别: 原始类型储存在
栈(Stack)
中储存变量的值,而引用类型在栈中保存的是所引用内容储存在堆(Heap)中的值
。类似于指针
的概念,引用类型并非储存变量真实数值而是地址
,所以对已引用类型的复制其实只是复制了相同的地址而非实际的变量值
。
js的数据类型及他们的内存图示
栈
:原始数据类型(undefined、boolean、null、Number、String
等)堆
:引用类型(数组、对象、函数
)
两种类型的区别是:存储位置不同;
原始数据类型直接存储在栈(stack)中的简单数据段,占据空间小、大小固定,属于被频繁使用数据,所以放入栈中存储
;引用数据类型存储在堆(heap)中的对象,占据空间大、大小不固定,如果存储在栈中,将会影响程序运行的性能;引用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址。当解释器寻找引用值时,会首先检索其在栈中的地址,取得地址后从堆中获得实体。
1. null
获取不存在的对象 document.getElementById('not-exist-element')
2. undefined
以声明为赋值的变量 var obj;
获取对象不存在的属性 var obj = {x: 0}; obj.y;
无返回值函数的执行结果 function f(){}; var obj = f();
函数参数没有传入 function f(i){console.log(i)}; f();
void(expression)
3. String
var str = 'Hello, world!';
4. Number
整型直接量,八进制直接量(0-),十六进制直接量(0x-),浮点型直接量 出现场景:
5. Boolean
条件语句导致的系统执行的隐式类型转换 if(隐式转换){}
字面量或变量定义 var bool = true;
6. Object
7. Symbol [ ES6 ]
复制代码
变量装换表
|Value |Boolean |Number| String| | :--------: | :--------:| :------: | |undefined| false |NaN| "undefined"| |null |false |0| "null"| |true |true| 1 |"true"| |false |false| 0 |"false"| |""| false| 0 |''| |'123' |true| 123 |'123'| |'1a' |true |NaN |'1a'| |0 |false| 0 |"0"| |1 |true| 1| "1"| |Infinity |true |Infinity |"Infinity"| |NaN |false |NaN |'NaN' |{} |true| NaN |"[object Object]"|
? 值和引用类型
1. 值类型: String. Number. Boolean. [ ?存储在栈中固定值常量]
{ 不太确定 Notice: undefined. null. Symbol [ ES6 ] }
null == null. null === null. // true
undefined == undefined. undefined ===undefined. // true ⚠️
2. 引用类型: Array. Object. Function.(⚠️Notice) [ ?存储在堆中]
var a = {a: '23'}; var b = {a: '23'};
false: a === b || a == b
复制代码
? 区分数据类型
前言:
typeof
Object.prototype.toString
constructor
instanceof
1. ??Object.prototype.toString.call(T)
- Array: "[object Array]"
- String: "[object String]"
- Object: "[object Object]"
- Symbol: "[object Symbol]"
- Number: "[object Number]"
- Boolean: "[object Boolean]"
- Function: "[object Function]"
- RegExp: "[object RegExp]"
- null: "[object Null]"
- undefined: "[object Undefined]"
- window[⚠️ !Window]: "[object Window]" ⚠️
2. typeof(T)
- Array: "object" ⚠️
- String: "string"
- Object: "object" ⚠️
- Function: "function"
- Number: "number"
- Symbol: "Symbol"
- Number: "number"
- Boolean: "boolean"
- Function: "function"
- RegExp: "object" ⚠️
- null: "object" ⚠️
- undefined: "undefined" ?
复制代码
? 你所不知道的高级技巧
typeof undefined // "undefined"
typeof new RegExp('23232') // "object"
typeof NaN // "number"
typeof null // "object"
null == null // true
null === null // true
undefined === undefined // true
undefined == undefined // true
null == undefined // true
null === undefined //false
⚠️ NaN 谁也不等,就是这么
NaN == NaN // false
NaN === NaN // false
Object.is(NaN, NaN) // true???
Function instanceof Object // true ??
// 说明function是对象
复制代码
1. 为什么typeof null 是 object?
从逻辑角度来看,
null值表示一个空对象指针
,而这正是使用typeof操作符检测null值时会返回“object”的原因。《JavaScript高级程序设计(第2版)》P22如是说
?: 娘胎里带出来的.
JS类型值是存在32 BIT 单元里,32位有1-3位表示TYPE TAG,其它位表示真实值 而表示object的标记位正好是低三位都是0 000: object. The data is a reference to an object. 而js 里的Null 是机器码NULL空指针, (0x00 is most platforms).所以空指针引用 加上 对象标记还是0,最终体现的类型还是object..这也就是为什么Number(null)===0吧...
- null不是一个空引用, 而是一个原始值, 参考ECMAScript5.1中文版 4.3.11节; 它只是期望此处将引用一个对象, 注意是"期望", 参考 null
- typeof null结果是object, 这是个历史遗留bug
- 在ECMA6中, 曾经有提案为历史平凡, 将type null的值纠正为null, 但最后提案被拒了. 理由是历史遗留代码太多, 不想得罪人, 不如继续将错就错当和事老
JavaScript类型检测之typeof 和 instanceof 的缺陷与优化
1. typeof
typeof 返回一个表达式的数据类型的字符串,返回结果为javascript中的基本数据类型,包括:number、boolean、string、object、undefined、function Symbol
等7种数据类型。
typeof 100; //number
typeof (1==1); //boolean
typeof 'onepixel'; //string
typeof {} ; //object
typeof onepixel; // undefined
typeof parseInt; // function
typeof [];//object
typeof new Date(); //object
复制代码
可以看出,typeof 可以准确的判断除object以外的基础数据类型,但不能区分object类型的具体类型,比如 Array 、Date 以及自定义类。
2. instanceof
String instanceof String //false
Object instanceof Object //true
Array instanceof Array //false
'' instanceof String // false
[1,2] instanceof Array
true
Date instanceof Date
false
'2' instanceof String
false
RegExp instanceof RegExp
false
复制代码
instanceof 本意是用来判断 A 是否为 B 的实例对象,表达式为:A instanceof B,如果A是B的实例,则返回true,否则返回false。 在这里需要特别注意的是:instanceof检测的是原型,那它是怎么检测的呢,我们用一段伪代码来模拟其内部执行过程:
instanceof (A,B) = {
var L = A.__proto__;
var R = B.prototype;
if(L === R) {
//A的内部属性__proto__指向B的原型对象
return true;
}
return false;
}
复制代码
从上述过程可以看出,当A的__proto__ 指向B的prototype时,就认为A就是B的实例对象,我们再来看几个例子:
[] instanceof Array; //true
{} instanceof Object;//true
new Date() instanceof Date;//true
function Person(){};
new Person() instanceof Person;
[] instanceof Object; //true
new Date() instanceof Object;//tru
new Person instanceof Object;//true
? ? ?
var a = '' ; a instanceof String //false
a = new String('2')// String {"2"}
a instanceof String //true
Number instanceof Number //false
b = new Number('23')
b instanceof Number // true
23 instanceof Number // false
/\d/i instanceof RegExp // true
a = {}
a instanceof Object // true
复制代码
从上面的例子中,我们发现虽然instanceof能够正确判断[] 是Array的实例对象,但不能辨别 [] 不是Object的实例对象,为什么呢,这还需要从javascript的原型链说起,我们首先来分析一下[]、Array、Object 三者之间的关系,从instanceof判断能够得出:[].proto ->Array.prototype, 而Array.prototype.__proto__指向了Object.prototype,Object.prototype.proto 指向了null,标志着原型链的结束。(ps:关于JS原型链请阅读:浅谈javascript原型和原型链) 因此,[]、Array、Object就形成了一条原型链:
从原型链可以看出,[]的__proto__最终指向了Object.prototype,类似的new Date()、new Person() 也会形成这样一条原型链,因此,我们用 instanceof 也不能完全精确的判断object类的具体数据类型。