js--闭包,作用域链

1.回顾执行环境及作用域
1.1执行环境execution context

执行环境定义了变量或函数有权访问的其他数据,决定了它们各自的行为。
变量对象:
每个执行环境都有一个与之关联的变量对象,环境中定义的所有变量和函数都保存在整个对象中。

1.2全局执行环境

全局执行环境是最外围的执行环境,在web浏览器中,全局执行环境被认为是window对象。

1.3变量的作用域

全局变量和局部变量

var n=999;//全局变量
function f1() {
    alert(n);
}
f1(); // 999
function f1(){
    var n=999;//局部变量
}
alert(n); // error,函数外部无法读取函数内部的局部变量
function f1(){    
    n=999;//不适用var,这样定义是全局变量
}
f1();
alert(n); // 999

其实,函数内部可以访问外部变量,但是外部变量不可访问函数的内部变量。

1.4作用域链

当代码在一个环境中执行时,会创建变量对象的一个作用域链。
用途:
保证对执行环境有权访问的所有变量和函数的有序访问。
js解释器会根据作用域链向上搜索,查询变量和函数名,作用域链的终点就是搜索到全局执行环境,但是不能通过向下搜索作用域链而进入另一个执行环境。
举例:
1.在创建函数时,会创建一个预先包含全局变量对象(比如windows对象等)的作用域链,作用域链被保存在内部的[[scope]]属性中
2.当函数compare()被调用时,会为函数创建一个执行环境,然后复制[[scope]]构造起执行环境的作用域链,且一个活动对象被创建并推入到执行环境作用域链的前端。如图
3.函数执行完毕后,局部活动对象被销毁,内存中仅保存全局作用域。

function compare(a,b){
    return a-b;
}//作用域链compare-->window

这里写图片描述

2.闭包

背景:
根据作用域和作用域链的原理,我们似乎不能在外部读取其它函数的内部变量。
闭包:
闭包就是能够读取其他函数内部变量的函数,在js中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成“定义在一个函数内部的函数”。
本质上,闭包是函数内外部的桥梁。
原理:
1.后台执行环境中,闭包的作用域链包含着自己的作用域、函数的作用域和全局作用域。
2.通常,函数的作用域和变量会在函数执行结束后销毁。
3.但是,当函数返回一个闭包时,这个函数的作用域将会一直在内存中保存到闭包不存在为止。
用途:
1.访问函数内部变量,就是实现面向对象的访问控制。也就是c++, c#, java等面向对象的private, public访问控制
2.将这些变量值始终保存在内存
缺点:
1.需要维护额外的作用域
2.过渡使用闭包会占用大量内存

eg1:通过返回内部函数实现闭包对函数内部数据的访问

function sayHello2(name) {
    var text = 'Hello ' + name; // Local variable
    var say = function() { 
        console.log(text); 
    }
    return say;
}
//可以访问函数内部变量,说明text被保存在了闭包中
var say2 = sayHello2('Bob');
say2(); // "Hello Bob"

eg1:闭包不是复制本地变量值保存, 而是提供关联本地变量(可理解成指针)

function say667() {
    var num = 666;
    var say = function() { console.log(num); }
    num++;
    return say;
}
var sayNumber = say667();
sayNumber(); //667
function foo(x) {

    var tmp = 3;
    return function (y) {
        alert(x + y + (++tmp));
    }
}
var bar = foo(2); // bar 现在是一个闭包
bar(10);

eg2:闭包不是复制本地变量值保存, 而是提供关联本地变量(可理解成指针)

var gLogNumber, gIncreaseNumber, gSetNumber;
function setupSomeGlobals() {
    // Local variable that ends up within closure
    var num = 666;
    // Store some references to functions as global variables
    gLogNumber = function() { console.log(num); }
    gIncreaseNumber = function() { num++; }
    gSetNumber = function(x) { num = x; }
}
//第一个闭包创建
setupSomeGlobals();
gIncreaseNumber();
gLogNumber(); // 667
gSetNumber(5);
gLogNumber(); // 5

var oldLog = gLogNumber;
//一个新的闭包被创建
setupSomeGlobals();
gLogNumber(); // 666

oldLog() // 5

闭包的实践,还没做很多,日后实践,再做补充,先行记录

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值