一、js中内存分为栈内存、堆内存此处引申知识点:js中堆栈内存及函数处理机制
栈内存
- 从数据类型角度思考 栈内存 存储基本数据类型的值、引用类型的指针、函数存储位置信息。
- 提供一个供js代码自上而下执行的环境(代码都是在栈中执行的)。
- 由于基本数据类型值比较简单,他们都是直接在栈内存中开辟一个位置,把值直接存储进去,当栈内存被销毁,存储的那些基本值也都跟着销毁了。
此处引申知识点:作用域(全局、函数、块级)
堆内存
- 从数据类型角度思考 堆内存 存储引用类型的值、函数的代码块。
- 存储引用类型的值(对象:键值对 函数:代码字符串)。
- 当前堆内存释放销毁,那么这个引用值彻底没了。
- 堆内存的释放:当堆内存没有被任何的变量或者其它东西所占用,浏览器会在空闲的时候,自主的进行内存回收,把所有不被占用的堆内存销毁掉。
- xxx = null 通过空对象指针null可以让原始变量(或者其他东西)谁都不指向,那么原有被占用的堆内存就没有被东西占用了,浏览器会销毁它。
此处引申知识点:引用类型的赋值、浅拷贝、深拷贝
js中数据类型
- 基本数据类型:number、string、boolean、null、undefined、symbol、bigint (栈内存)
- 引用数据类型:Object、Array、Date、Function、Regexp (堆内存)
数据类型检测方法
1. typeof
- 对于基本类型,除null以外,均可以返回正确的结果。
- 对于引用类型,除function以外,一律返回object类型。
- 对于null,返回object类型。
- 对于function,返回function类型。
typeof '' // 'string'
typeof 123 // 'number'
typeof Symbol() // 'symbol'
typeof true // 'boolean'
typeof undefined // 'undefined'
typeof new Function() // 'function'
typeof null // 'object'
typeof [] // 'object'
typeof new Date() // 'object'
typeof new RegExp() // 'object'
typeof new Error() // 'object'
typeof document // 'object'
typeof window // 'object'
比较适合检测基本数据类型,在一些源码中使用示例:
line37:https://github.com/vuejs/vue/blob/dev/dist/vue.js#L14-L379
/**
* Check if value is primitive.
*/
function isPrimitive(value) {
return (
typeof value === "string" ||
typeof value === "number" ||
// $flow-disable-line
typeof value === "symbol" ||
typeof value === "boolean"
);
}
2. instanceof
instanceof 是用来判断A是否为B的实例,表达式为:A instanceof B,如果A是B的实例,则返回true,否则返回false。instanceof检测的是原型,通过原型链来判断。 instanceof 只能用来判断两个对象是否属于实例关系,而不能判断一个对象实例具体属于哪种类型。
此处引申知识点:js原型、原型链
instanceof(A, B) = {
let a = A.__proto__
let b = B.prototype
if (a === b) {
return true
}
return false
}
function Person() {}
let man = new Person()
man instanceof Person // true
man instanceof Object // true
let test = new String('message')
console.log(test instanceof String) // true
console.log(test instanceof Object) // true
let test = 'message'
console.log(test instanceof String) // false
console.log(test instanceof Object) // false
Array.isArray()鉴别数组的最好方法
3. constructor
构造函数: function Person()
构造函数的原型: Person.Protptype,此原型上有一个constructor构造属性指向构造函数 Person,Person.Protptype.constructor === Person
实例对象: let man = new Person(),此时Person.Protptype.constructor传递到man上,man.constructor === Person
此处引申知识点:js原型、实例对象
function Person() {}
let man = new Person()
console.log(Person.prototype.constructor === Person) // true
console.log(man.constructor === Person) // true
'xixin'.constructor === String // true
new Number(123).constructor === Number // true
true.constructor === Boolean // true
Symbol().constructor === Symbol // true
new Function().constructor === Function // true
new Error().constructor === Error // true
new Date().constructor === Date // true
[].constructor === Array // true
document.constructor === HTMLDocument // true
window.constructor === Window // true
- null 和 undefined 是无效的对象,因此是不会有constructor存在的,这两种类型的数据类型需要通过其他方式来判断。
- 函数的constructor是不稳定的,这个主要体现在自定义对象上,当开发者重写prototype后,原有的constructor引用会丢失。
function Root () {
this.name = '小程'
this.arr = [1,2,3]
}
function Person() {}
Person.prototype = new Root()
let man = new Person()
console.log(man.constructor)
console.log(man.constructor === Root) // true
function Person() {}
Person.prototype = {
name: '小程',
arr: [1,2,3]
}
let man = new Person()
console.log(man.constructor)
console.log(man.constructor === Object) // true
4. Object.prototype.toString.call()
toString() 方法返回一个表示该对象的字符串,每个对象都有一个 toString()
方法,当该对象被表示为一个文本值时,或者一个对象以预期的字符串方式引用时自动调用。默认情况下,toString()
方法被每个 Object
对象继承。如果此方法在自定义对象中未被覆盖,toString()
返回 "[object type]",其中 type
是对象的类型。
let obj = new Object()
obj.toString() // 返回 [object, object]
备注: 如 ECMAScript 5 和随后的 Errata 中所定义,从 JavaScript 1.8.5 开始,toString()
调用 null
返回[object Null]
,undefined
返回 [object Undefined]
。
(Object.prototype.toString.call(value).slice(8, -1)) // 获取到类型值
(Object.prototype.toString.call('123').slice(8, -1)) => // 'String'
let toString = Object.prototype.toString
toString.call('') // [Object String]
toString.call(1) // [Object Number]
toString.call(true) // [Object Boolean]
toString.call(Symbol) // [Object Symbol]
toString.call(new Function()) // [Object Function]
toString.call(new Date()) // [Object Date]
toString.call([]) // [Object Array]
toString.call(new RegExp()) // [Object RegExp]
toString.call(new Error()) // [Object Error]
toString.call(document) // [Object HTMLDocument]
toString.call(window) // [Object Window] 浏览器环境
toString.call(window) // [object global] node环境
// since JavaScript 1.8.5
toString.call(undefined); // [object Undefined]
toString.call(null); // [object Null]