闭包&变量提升&内存释放

248 阅读1分钟

首先看下函数声明

function fucName (arg1, arg2) {}
// 匿名函数
var fuc1 = function () {}   // 必须先声明才能调用

闭包

简单的说就是函数中再写函数,它能够访问到上层函数的变量,解决函数作用域的问题

for (var i = 1; i <= 5; i++) {
	setTimeout(
	(function timer() {
		console.log(i); //1,2,3,4,5
	})
	(), i * 1000);
}

变量/函数提升

变量跟函数都可以被提升,这也是为什么匿名函数必须先声明

var num = 0;
func();  // 报错
var func = function () {console.log(num)};

提升后

var num;
var func;   // undefinde
num = 0;
func(); // not a function
func = function () {}

在js解析过程中会先进行变量提升和加分号的一些预处理操作,会把函数及变量声明语句提升,甚至变量可以不使用var声明

num2 = 4;
console.log(num2)

但最好不要这样做,可以使用es6的let声明,来使代码更加严谨、可读

num2 = 4;   //Cannot access 'num2' before initialization
console.log(num2)
let num2;

以及一些经典面试题

var num = 1;
function bar() {
    if (!num) {
        var num = 10;
    }
    console.log(num); 
}
bar();//   10

甚至

function Foo() {
	getName = function() {
		console.log("1");
	};
	return this;
}
Foo.getName = function() {
	console.log("2");
};

Foo.prototype.getName = function() {
	console.log("3");
};

var getName = function() {
	console.log("4");
};

function getName() {
	console.log("5");
}
Foo.getName(); 			// 2 
getName(); 				// 4
Foo().getName(); 		// 1   
getName(); 				// 1
new Foo.getName(); 		// 2
new Foo().getName(); 	// 3
new new Foo().getName(); // 3

内存释放

  • 写一个闭包
var  f = function () {
    var num = 0;
    return function () {
        num += 1;
    }
}

f()();      // 1
f () ();    // 1

num并没有自增,每一次调用后内存释放了num重置

var fn = f();
fn();   // 1
fn();   // 2
fn();   // 3
fn = null;  // 手动释放
fn = f();
fn();   // 1