1.JS中的8种数据类型及区别
包括值类型(基本对象类型)和引用类型(复杂对象类型)
- 基本类型(值类型): Number(数字),String(字符串),Boolean(布尔),Symbol(符号),null(空),undefined(未定义)在内存中占据固定大小,保存在栈内存中
- 引用类型(复杂数据类型): Object(对象)、Function(函数)。其他还有Array(数组)、Date(日期)、RegExp(正则表达式)、特殊的基本包装类型(String、Number、Boolean) 以及单体内置对象(Global、Math)等
- 引用类型的值是对象 保存在堆内存中,栈内存存储的是对象的变量标识符以及对象在堆内存中的存储地址。
2.JS中的数据类型检测方案
- typeof
console.log(typeof 1);
// numberconsole.log(typeof true);
// booleanconsole.log(typeof 'xx');
// stringconsole.log(typeof Symbol)
// functionconsole.log(typeof function(){});
// functionconsole.log(typeof console.log());
// functionconsole.log(typeof []);
// object console.log(typeof {});
// objectconsole.log(typeof null);
// objectconsole.log(typeof undefined);
- 优点:能够快速区分基本数据类型
- 缺点:不能将Object、Array和Null区分,都返回object
- instanceof
console.log(1 instanceof Number);
// falseconsole.log(true instanceof Boolean);
// false console.log('str' instanceof String);
// false console.log([] instanceof Array);
// trueconsole.log(function(){} instanceof Function);
// trueconsole.log({} instanceof Object);
-
优点:能区分Array、Object和Function,适合用于判断自定义的类实例对象
-
缺点:Number,Boolean,String基本数据类型不能判断
- Object.prototype.toString.call()
var toString = Object.prototype.toString;console.log(toString.call(1));
//[object Number]console.log(toString.call(true));
//[object Boolean]console.log(toString.call('mc')); //[object String]console.log(toString.call([]));
//[object Array]console.log(toString.call({}));
//[object Object]console.log(toString.call(function(){}));
//[object Function]console.log(toString.call(undefined));
//[object Undefined]console.log(toString.call(null));
- 优点:精准判断数据类型
- 缺点:写法繁琐不容易记,推荐进行封装后使用
3.var && let && const
ES6之前创建变量用的是var,之后创建变量用的是let/const
三者区别:
- var定义的变量,没有块的概念,可以跨块访问, 不能跨函数访问。
let定义的变量,只能在块作用域里访问,不能跨块访问,也不能跨函数访问。
const用来定义常量,使用时必须初始化(即必须赋值),只能在块作用域里访问,且不能修改。 - var可以先使用,后声明,因为存在变量提升;let必须先声明后使用。
- var是允许在相同作用域内重复声明同一个变量的,而let与const不允许这一现象。
- 在全局上下文中,基于let声明的全局变量和全局对象GO(window)没有任何关系 ;
var声明的变量会和GO有映射关系; - 会产生暂时性死区:
暂时性死区是浏览器的bug:检测一个未被声明的变量类型时,不会报错,会返回undefined
如:console.log(typeof a) //undefined
而:console.log(typeof a)//未声明之前不能使用let a
let /const/function会把当前所在的大括号(除函数之外)作为一个全新的块级上下文,应用这个机制,在开发项目的时候,遇到循环事件绑定等类似的需求,无需再自己构建闭包来存储,只要基于let的块作用特征即可解决
4.JS垃圾回收机制
项目中,如果存在大量不被释放的内存(堆/栈/上下文),页面性能会变得很慢。当某些代码操作不能被合理释放,就会造成内存泄漏。我们尽可能减少使用闭包,因为它会消耗内存。
-浏览器垃圾回收机制/内存回收机制:
浏览器的Javascript具有自动垃圾回收机制(GC:Garbage Collecation),垃圾收集器会定期(周期性)找出那些不在继续使用的变量,然后释放其内存。
在js中,最常用的垃圾回收机制是标记清除:当变量进入执行环境时,被标记为“进入环境”,当变量离开执行环境时,会被标记为“离开环境”。垃圾回收器会销毁那些带标记的值并回收它们所占用的内存空间。
谷歌浏览器:“查找引用”,浏览器不定时去查找当前内存的引用,如果没有被占用了,浏览器会回收它;如果被占用,就不能回收。
IE浏览器:“引用计数法”,当前内存被占用一次,计数累加1次,移除占用就减1,减到0时,浏览器就回收它。
优化手段:内存优化 ; 手动释放:取消内存的占用即可。
(1)堆内存:fn = null 【null:空指针对象】
(2)栈内存:把上下文中,被外部占用的堆的占用取消即可。
5.内存泄漏
在 JS 中,常见的内存泄露主要有 4 种,全局变量、闭包、DOM 元素的引用、定时器
参考书籍:《Javascript高级程序设计》