首先看下函数声明
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