conan1992 / blog

记录下知识点..
3 stars 0 forks source link

作用域、作用域链、闭包 #32

Open conan1992 opened 4 years ago

conan1992 commented 4 years ago

作用域

作用域定义了变量或函数访问其他数据的权限;

作用域类别

作用域分为词法作用域和动态作用域,JavaScript采用的是词法作用域,也就是静态作用域;也就是说作用域在定义函数的时候就生成了;

var value = 1;

function foo() {
    console.log(value);
}

function bar() {
    var value = 2;
    foo();
}

bar();// 打印:1;

作用域链

当访问一个变量时,解释器会首先在当前作用域查找标示符,如果没有找到,就去父作用域找,直到找到该变量的标示符或者不在父作用域中,这样由多个作用域形成的链表就叫做作用域链

闭包

闭包是指有权访问另外一个函数作用域中的变量的函数(红宝石书); 闭包是指那些能够访问自由变量的函数(MDN);

var value = 1;
function foo() {
    var value = 2;
    function bar(){
        console.log(value)
    }
    return bar;
}

var baz = foo();
baz();//输出2

上面这个例子就很好的证明了“静态作用域”;作用域在函数定义的时候就已经决定了,value先访问自身作用域存不存在value,再到父级foo作用域查找,找到value=2,所以输出为2;

闭包表现形式

function baz(fn){ fn(); } foo()//输出2

### 闭包应用
```html
<!DOCTYPE html>
<html lang="zh-cmn-Hans">

<head>
    <meta charset="utf-8">
    <meta http-equiv="x-ua-compatible" content="IE=edge, chrome=1">
    <title>waiting</title>
    <style>
        * { padding: 0; margin: 0;}
        body {display: grid;}
        li:nth-child(odd){ background:#eee;}
    </style>
</head>

<body>
    <ul>
        <li>1</li>
        <li>2</li>
        <li>3</li>
    </ul>
</body>
<script>
    var lis = document.querySelectorAll("li");
    var len = lis.length;
    for(var i=0;i<len;i++){
        lis[i].onclick = function(){
            console.log(i)
        }
    }
</script>
</html>

三次打印都为3; image

for(var i=0;i<len;i++){
        (function(j){
            lis[j].onclick = function(){
                console.log(j)
            }
        })(i);
    }

或者使用es6的块级作用域

for(let i=0;i<len;i++){
        lis[i].onclick = function(){
            console.log(i)
        }
    }

参考