第一版请见:WEB前端常见面试题及答案
1、js内存机制
JS内存空间分为栈(stack)、堆(heap)、池(一般也会归类为栈中)。 其中栈存放变量,堆存放复杂对象,池存放常量。
JS环境中分配的内存一般有如下生命周期:
内存分配:当我们申明变量、函数、对象的时候,系统会自动为他们分配内存
内存使用:即读写内存,也就是使用变量、函数等
内存回收:使用完毕,由垃圾回收机制自动回收不再使用的内存(这个是重点)
JavaScript有自动垃圾收集机制,那么这个自动垃圾收集机制的原理是什么呢?其实很简单,就是找出那些不再继续使用的值,然后释放其占用的内存。垃圾收集器会每隔固定的时间段就执行一次释放操作。 在JavaScript中,最常用的是通过标记清除的算法来找到哪些对象是不再继续使用的。Google的V8引擎使用的是分代管理,即标记为新生代和老生代。
在局部作用域中,当函数执行完毕,局部变量也就没有存在的必要了,因此垃圾收集器很容易做出判断并回收。但是全局变量什么时候需要自动释放内存空间则很难判断,因此在我们的开发中,需要尽量避免使用全局变量,以确保性能问题。
2、基础数据类型和引用数据类型
js中有7种数据类型:Undefined、Null、Boolean、Number、String和Symbol。
还有一种复杂的数据类型Object,Object本质是一组无序的名值对组成的。
JavaScript 标准文档中定义: [[Class]] 的值只可能是下面字符串中的一个: Arguments, Array, Boolean, Date, Error, Function, JSON, Math, Number, Object, RegExp, String. 这些内置对象都属于Object.
3、你不知道的JavaScript
见链接:你不知道的JavaScript
4、如何判断一个对象是不是数组
考虑使用typeof
console.log(typeof null); // "object"
console.log(typeof function () {
return 1;
}); // "function"
console.log(typeof 'aaa'); // "string"
console.log(typeof 1); // "number"
console.log(typeof a); // "undefined"
console.log(typeof undefined); // "undefined"
console.log(typeof []) //"object"
可以看到,利用typeof除了array和null判断为object外,其他的都可以正常判断。所以typeof无法被用来判断一个对象是否是数组,下面我们尝试使用instanceof来进行判断:
console.log([] instanceof Array) // true
console.log([].constructor === Array); // true
因为这个操作符是检测对象的原型链是否指向构造函数的prototype对象的,所以我们可以看到这个是可以判断成功的。同理,constructor也是可以判断的。两者其实都是使用了原型链,但是存在缺陷,如跨frame实例化的对象彼此是不共享原型链的,这两个方法就不行了。下面看看其他方法:
Object.prototype.toString
var a = [];
var b = function(){}
var c = {};
var d = 'aaa';
console.log(Object.prototype.toString.call(a)) // "[object Array]"
console.log(Object.prototype.toString.call(b)) // "[object Function]"
console.log(Object.prototype.toString.call(c)) // "[object Object]"
console.log(Object.prototype.toString.call(d)) // "[object String]"
Object.prototype.toString的行为:首先,取得对象的一个内部属性[[Class]],然后依据这个属性,返回一个类似于"[object Array]"的字符串作为结果(看过ECMA标准的应该都知道,[[]]用来表示语言内部用到的、外部不可直接访问的属性,称为“内部属性”)。利用这个方法,再配合call,我们可以取得任何对象的内部属性[[Class]],然后把类型检测转化为字符串比较,以达到我们的目的。
Array.isArray()
ECMAScript5将Array.isArray()正式引入JavaScript,目的就是准确地检测一个值是否为数组。IE9+、 Firefox 4+、Safari 5+、Opera 10.5+和Chrome都实现了这个方法。但是在IE8之前的版本是不支持的。这个也是最简洁的方法。