笔记的知识大部分来自 https://www.cnblogs.com/wangfupeng1988/p/3992795.html和<JavaScript权威指南>
1. 作用域
自由变量:在A作用域中使用的变量x,却没有在A作用域中声明(即在其他作用域中声明的),对于A作用域来说,x就是一个自由变量
看到这样一段代码,对fn来说,x就是自由变量
var x = 10;
function fn() {
console.log(x);
}
function show(f) {
var x = 20;
f();
}
show(fn); //10
这个代码执行出来是10。
原因: 要到创建这个函数的那个作用域中取值——是“创建”,而不是“调用”,其实这就是所谓的“静态作用域”。去创建fn函数的那个作用域中取——无论fn函数将在哪里调用。
上面描述的只是跨一步作用域去寻找。
如果跨了一步,还没找到呢?——接着跨——一直跨到全局作用域为止。要是在全局作用域中都没有找到,那就是真的没有了。
这个一步一步“跨”的路线,我们称之为——作用域链。
取自由变量时的这个“作用域链”过程:(假设a是自由量)
第一步,现在当前作用域查找a,如果有则获取并结束。如果没有则继续;
第二步,如果当前作用域是全局作用域,则证明a未定义,结束;否则继续;
第三步,(不是全局作用域,那就是函数作用域)将创建该函数的作用域作为当前作用域;
第四步,跳转到第一步。
我之前一直是简单记为从内向外找变量直到找到window下。
在网上还找了一个例子,结合上面的说明,倒是有点理解输出结果了:
function f1(){
var n=999;
nAdd=function(){n+=1}
function f2(){
console.log(n);
}
return f2;
}
var result=f1();
result(); // 999
nAdd();
result(); // 1000
2. 闭包
两种情况:函数作为返回值, 函数作为参数
2.1 函数作为返回值
function fn() {
var max = 10;
return function bar(x) {
if(x > max){
console.log(x);
}
}
}
var f1 = fn();
f1(15); //15
怎么取的max,就如同前面作用域讲得那样:去创建fn函数的那个作用域中取——无论fn函数将在哪里调用。
2. 2 函数作为参数
var max = 10;
fn = function (x) {
if(x > max){
console.log(x); //15
console.log(max); //10
}
}
;(function(f) {
var max = 100;
f(15);
})(fn);
同样的道理,fn里面取max就是在fn定义的作用域里面取max,即第一行 var max = 10;
在<JavaScript权威指南>里面,8.6闭包这一章有几句原话:
“函数的执行依赖于变量作用域,这个作用域是函数定义时决定的,而不是函数调用时决定的。”
“函数体内的变量都可以保存在函数作用域内,这种特性在计算机科学文献中称为‘闭包’。”
“函数定义时的作用域链到函数执行时仍然有效。”
以上三句箴言默念几遍以后,不管内在原理懂没有,至少函数变量取值会看了吧。
作用域和闭包暂且到此吧,因为我水平不够,再多复制粘贴大神的自己也无收获,此处写下的算是我能hold住的,其余等技术上升后再补充吧。