{ }
包括,let和const具有块级作用域,var不存在块级作用域。块级作用域解决了ES6中的两个问题:
垃圾回收的概念:JavaScript代码运行时,需要分配内存空间来储存变量和值。当变量不在参与运行时,就需要系统收回被占用的内存空间,这就是垃圾回收。
回收机制:
Javascript 具有自动垃圾回收机制,会定期对那些不再使用的变量、对象所占用的内存进行释放,原理就是找到不再使用的变量,然后释放掉其占用的内存。
JavaScript中存在两种变量:局部变量和全局变量。全局变量的生命周期会持续到页面卸载;而局部变量声明在函数中,它的生命周期从函数执行开始,直到函数执行结束,在这个过程中,局部变量会在堆或栈中存储它们的值,当函数执行结束后,这些局部变量不再被使用,它们所占有的空间就会被释放。
不过,当局部变量被外部函数使用时,其中一种情况就是闭包,在函数执行结束后,函数外部的变量依然指向函数内部的局部变量,此时局部变量依然在被使用,所以不会回收。
function outer(){
let i = 1
function fn(){
console.log(i)
}
return fn
}
const fun = outer()
fun() // 返回1
// 外层函数使用内部函数的变量
垃圾回收的方式:
引用计数法:IE采用的引用计数算法,定义“内存不再使用”,就是看一个对象是否有指向它的引用,没用引用了就回收对象。
算法:
但引用计数法存在一个致命的问题:嵌套引用(循环引用)。
如果两个对象相互引用,尽管他们已不再使用,垃圾回收器不会进行回收,导致内存泄露,因为他们的引用次数永远不会是0,这样的相互引用如果大量存在会导致大量的内存泄露。
标记清除法:现代的浏览器已经不再使用引用计数算法,使用的大多是基于标记清除算法的某些改进算法,总体思想都是一致的。
核心:
var tmp = new Date();
function fn(){
console.log(tmp);
if(false){
var tmp = 'hello world';
}
}
fn();
答案:undefined。
解释:var存在变量提升,var声明的变量会被提升到作用域的顶层,但该声明不包括赋值,所以虽然if判断里的语句虽然并不会执行,但其实已经在fn函数作用域内的顶部声明了一个未被赋值的tmp变量,所以console.log(tmp)
打印出来的结果是undefined。
var name = "window";
var person = {
name: "person",
sayName: function () {
console.log(this.name);
},
hello: () => console.log(this.name)
};
function sayName() {
var sss = person.sayName;
sss();
person.sayName();
(person.sayName)();
(b = person.sayName)();
person.hello()
}
sayName();
调用sss();
后this指向window。
原因:当函数被作为普通函数调用时,this指向全局对象(在浏览器中是
window
,在Node.js中是global
),或者在严格模式('use strict'
)下,this
是undefined
。
调用person.sayName();
后this指向person。
原因:当函数被作为对象的方法调用时,
this
指向该对象。
调用(person.sayName)();
后this指向person。
原因:当函数被作为对象的方法调用时,
this
指向该对象。
调用(b = person.sayName)();
后this指向window。
原因:当函数被作为普通函数调用时,this指向全局对象(在浏览器中是
window
,在Node.js中是global
),或者在严格模式('use strict'
)下,this
是undefined
。
调用后person.hello()
this指向window
原因:箭头函数不绑定自己的
this
,它会捕获其所在上下文的this
值,作为自己的this
值。
JavaScript中实现数组扁平化(即将多维数组转换为一维数组)有多种方法,以下是一些常见的方法:
递归是处理嵌套结构如多维数组的一个直观方法。你可以编写一个函数,该函数检查数组中的每个元素,如果元素是数组,则递归调用该函数;否则,将元素添加到结果数组中。
function flattenArray(arr) {
let result = [];
for (let i = 0; i < arr.length; i++) {
if (Array.isArray(arr[i])) {
result = result.concat(flattenArray(arr[i]));
} else {
result.push(arr[i]);
}
}
return result;
}
console.log(flattenArray([1, [2, [3, [4]], 5]])); // 输出: [1, 2, 3, 4, 5]
迭代方法结合栈也是处理数组扁平化的有效方式。我们可以将数组元素逐一压入栈中,并在遇到数组时将其元素再次压入栈中,直到栈为空。
function flattenArrayWithStack(arr) {
let stack = [...arr];
let res = [];
while (stack.length) {
// 取出栈的最后一个元素
const next = stack.pop();
if (Array.isArray(next)) {
// 如果是数组,则将数组元素逆序压入栈中
// 这样可以保证原始数组的顺序在结果中被保留
stack.push(...next.reverse());
} else {
// 否则,将元素添加到结果数组中
res.push(next);
}
}
// 因为我们是从栈中取元素,所以结果数组是逆序的,需要反转
return res.reverse();
}
console.log(flattenArrayWithStack([1, [2, [3, [4]], 5]])); // 输出: [1, 2, 3, 4, 5]
reduce
这种方法利用了ES6的扩展运算符...
和数组的reduce
方法,通过递归的方式实现扁平化。
function flattenArrayWithReduce(arr) {
return arr.reduce((acc, val) => Array.isArray(val) ? [...acc, ...flattenArrayWithReduce(val)] : [...acc, val], []);
}
console.log(flattenArrayWithReduce([1, [2, [3, [4]], 5]])); // 输出: [1, 2, 3, 4, 5]
flat()
(ES2019引入)从ES2019开始,JavaScript引入了一个名为flat()
的数组方法,它可以用来实现数组的扁平化,其默认只会扁平化一层,但你可以通过传递一个整数参数来指定扁平化的深度,如果深度为Infinity
,则表示无论嵌套多少层都将被扁平化。
const arr = [1, [2, [3, [4]], 5]];
console.log(arr.flat(Infinity)); // 输出: [1, 2, 3, 4, 5]
这是最简单也最现代的方法,但请注意,它可能不适用于需要兼容较旧JavaScript环境的场景。
题目:给定某无序数组,要求去除数组中的重复数字并且返回新的无重复数组。
解答:
Set
数据结构Set
是一个构造函数,它创建一个值的集合,其中的值都是唯一的,没有重复的值。因此,将数组转换为Set
,然后再转换回数组,可以实现去重。
function uniqueArray(arr) {
return [...new Set(arr)];
}
console.log(uniqueArray([1, 2, 2, 3, 4, 4, 5])); // 输出: [1, 2, 3, 4, 5]
filter()
和indexOf()
遍历数组,对于当前元素,使用indexOf()
检查它首次出现的位置是否和当前位置相同,如果相同,则说明不是重复元素,将其保留。
function uniqueArray(arr) {
return arr.filter((item, index) => arr.indexOf(item) === index);
}
console.log(uniqueArray([1, 2, 2, 3, 4, 4, 5])); // 输出: [1, 2, 3, 4, 5]
但需要注意的是,这种方法在数组元素为对象时可能不适用,因为对象比较是基于引用的。
Map
数据结构类似于Set
,Map
也是一个集合,但它保存键值对。我们可以利用它的键是唯一的特性来实现去重。
function uniqueArray(arr) {
const map = new Map();
arr.forEach(item => map.set(item, true));
return Array.from(map.keys());
}
console.log(uniqueArray([1, 2, 2, 3, 4, 4, 5])); // 输出: [1, 2, 3, 4, 5]
reduce()
reduce()
方法可以对数组中的每个元素执行一个由您提供的reducer函数(升序执行),将其结果汇总为单个返回值。我们可以利用这一点来构建一个新的数组,只包含不重复的元素。
function uniqueArray(arr) {
return arr.reduce((acc, current) => {
if (acc.indexOf(current) === -1) {
acc.push(current);
}
return acc;
}, []);
}
console.log(uniqueArray([1, 2, 2, 3, 4, 4, 5])); // 输出: [1, 2, 3, 4, 5]
Number、Object、BigInt、Symbol、String、Boolean、Undefined、Null
ES6新增:Symbol、Bigint