1 谈谈你眼中的闭包
个人理解,闭包就是在一个函数内创建另一个函数,创建的子函数可以有权限 访问到当前父函数的局部变量。相当于是函数内部与函数外部建立沟通的一个桥梁
作用:
变量私有化,能延长变量的生命周期
缺点:
闭包太消耗内存了,容易造成内存泄漏
解决方案:
退出闭包的时候将不要的变量名删除,或者直接赋值为null
应用场景:
模块化开发,封装函数,沙箱(分割作用域,避免全局变量污染)
function a(){
var n = 0;
function add(){
n++;
console.log(n);
}
return add;
}
var a1 = a(); //注意,函数名只是一个标识(指向函数的指针),而()才是执行函数;
a1(); //1
a1(); //2 第二次调用n变量还在内存中
其实闭包的本质就是作用域链的一个特殊的应用,只要了解了作用域链的创建过程,就能够理解闭
2 作用域和作用域链
js作用域:
变量在某个范围内起作用和效果,目的是为了提高程序的可靠性,减少命名冲突
全局作用域:
整个script标签或者是一个单独的js文件
局部作用域:(函数作用域)
在函数内部就是局部作用域,变量名只在函数内部起作用和效果
var num = 10; // 全局
function tn() {
var num = 20; // 局部
console.log(num); // 20
}
tn()
console.log(num); // 10
var num = 10; // 全局
console.log(num); // 10
function tn() {
var num = 20; // 局部
console.log(num); // 20
}
function fn() {
num = 30 // 全局
// 在函数内部,没有声明直接赋值的变量也属于全局变量
}
tn()
fn()
console.log(num); // 30
函数的形参也可以看做是局部变量
全局变量只有浏览器关闭时才会销毁,比较占内存
局部变量 当我们程序执行完毕才会销毁,比较节约内存
在es6 之前没有块级作用域,暂时只有全局作用域, 局部作用域,
es6才新增块级作用域. (全局作用域, 局部作用域, 块级作用域)块级作用域 {} : if {} , for(){ }
// es5 无块级作用域
if (true) {
var cool = 'yy'
}
console.log(cool); // 'yy'
// es6 块级作用域
if (1<2) {
let num = 123
}
console.log(num); // num is not defined
js作用域链
内部函数访问外部函数的变量,采取的是链式查找的方式来决定采取那个值,这种结构我们称为作用越链 (就近原则)
var num = 520
function withoutFn() {
var num = 999
function insideFn() {
console.log(num); // 999
}
insideFn()
}
withoutFn()
答案是 123
a是 4 ,
b是 ‘22’
3 预解析
js引擎运行js 分为两步: 1 预解析 2 代码执行
预解析:
(1) js引擎会把js里面所有的 var 还有 function 提升到当前作用域的最前面
(2) 预解析分为 变量解析 (变量提升) 和 函数预解析 (函数提升)
(3) 变量提升 把所有的变量声明提升到当前作用域最前面,但 不提升赋值操作
(4) 函数提升 把所有的函数声明提升到当前作用域最前面 不调用函数
代码执行: 按照代码书写的顺序从上往下执行
console.log(num); // undefined (因为预解析的原因)
var num = 123
// 等同下面的代码
var num
console.log(num);
num = 123
fn() // fn is not a function
var fn = function () {
console.log(567);
}
// 相当于执行了一下代码
// 变量提升 把所有的变量声明提升到当前作用域最前面,但不提升赋值操作
var fn
fn()
fn = function(){
console.log(567);
}
fn() // 打印 '梅花13'
function fn() {
console.log('梅花13');
}
// 相当于执行了一下代码
// 函数提升 把所有的函数声明提升到当前作用域最前面 不调用函数
function fn() {
console.log('梅花13');
}
fn()
案例测试
// 案例1
var num = 10
fun()
function fun (){
console.log(num)
var num = 20
}
// 结果打印 undefined
// 案例2
var num = 10
function fn (){
console.log(num)
var num = 20
console.log(num);
}
fn()
// 答案 undefined 20
// 等同于以下代码
var num
function fn() {
var num
console.log(num)
num = 20
console.log(num);
}
num = 10
fn()
// 案例三
fn()
console.log(c);
console.log(b);
console.log(a);
function fn() {
var a = b = c = 9
console.log(a);
console.log(b);
console.log(c);
}
// 等同于一下代码
function fn() {
var a
a = b = c = 9
// 相当于var a = 9; b = 9; c = 9, b和c直接赋值,没有var声明当全局变量看
// 集体声明 var a=9,b=9,c=9
console.log