JS——作用域 && 闭包
2017-09-20 10:02
155 查看
执行上下文
范围
一段<script>或者一个函数
全局(一段<script>
)执行顺序
变量定义函数声明
函数执行顺序
变量定义函数声明
设定this
传入参数
consloe.log(a); // undefined var a = 100; fn("Tim Chen"); // Tim Chen 20 function fn(name){ age = 20; console.log(name,age); var age; }
第一个例子里执行顺序
var a = undefined; console.log(a); a = 20 ;
a还没有赋值,便已经打印了。所以最终结果是undefined。
第二个例子里执行顺序
function fn(name){ var age = undefined; age = 20; console.log(name,age); }; fn("Tim Chen");
函数内部先声明变量,传入参数,然后对变量进行赋值,打印。
函数已经声明了,所以调用是可以执行的。
this
this要在执行时才能确定值,定义时无法确定。var a = { name: "A", fn: function(){ console.log(this.name); } } a.fn(); // this === a a.fn.call({name: "B"}); // this === {name : "B"} var fn1 = a.fn; fn1(); // this === window
构造函数使用
function Foo(name){ this.name = name; } var f = new Foo("Tim Chen");
对象属性使用
var a = { name: "A", fn: function(){ console.log(this.name); } } a.fn();
普通函数使用
此时打印出来的结果是windowfunction fn(){ consoloe.log(this); } fn();
call/apply/bind使用
call()此时打印出来的this === {x: 100}
function fn(name){ alert(name); consoloe.log(this); } fn.call({x:100},"Tim Chen");
bind()
bind()只能是函数表达式用
var fn = function(name,age){ alert(name); console.log(this); }.bind({y:200}); fn("Tim Chen","22");
作用域
es5及以前,无块级作用域。只有函数和全局作用域。
无块级作用域怎么理解?
所谓的块级作用域,就是说{}括号里自成一体,括号外访问不了括号内的变量、参数。
if(true){ var str = "成功读取"; } console.log(str); // 成功读取
上面的代码,从{}外面依然可以访问到里面的str变量。
函数和全局作用域
var a =100; function fn(){ var a = 200; console.log("fn",a); //打印出来是函数内的变量a } console.log("global",a); //打印出来是全局变量a fn();
作用域链
如果函数调用了,当前作用域没有定义的变量(自由变量),它会去父级作用域找。父级也没有,就继续网上找。这就叫作用域链。
注意,这个父级作用域指的是函数在定义时的父级,而不是执行时的父级。
var a = 100; function fn (){ var b = 200; console.log(a); // } fn();
闭包
function F1(){ var a = 100; //返回值是一个函数 return function(){ console.log(a); } } //fn1 得到一个函数 var fn1 = F1(); var a = 200; fn1();
fn1执行的时候,其实就是执行console.log(a)。
上面的作用域链提到过,作用域调用自由变量的时候,会去它定义时的父级作用域寻找。在这个例子里,父级就是 F1函数。
所以最终执行的结果是100。
使用场景
函数作为返回值(上面的例子)函数作为参数传递
请看代码
function F1(){ var a = 100; return function(){ console.log(a); } } var fn1 = F1(); function F2(fn){ var a = 200; fn(); } F2(fn1);
还是那句话,自由变量会去它定义时的父级作用域寻找。
而不是调用时的作用域!!!
所以最终执行的结果是100。
闭包在实际开发中的应用
封装变量,限制权限。function isFirstLoad(){ var _list = []; return function (id){ if(_list.indexOf(id)>=0){ return false; }else{ _list.push(id); return true; } } } //调用 var firstLoad = isFirstLoad(); firstLoad(10); //true firstLoad(10); //false firstLoad(20); //true
例题讲解
1. 变量提升的理解(执行上下文)
变量定义函数声明
2. 创建10个标签,点击弹出相应序号
错误写法:var i , a; for(i = 0; i < 10; i++){ a.document.createElement("a"); a.innerHTML = i +"<br />"; a.addEventListener("click",function(e){ e.preventDefault(); alert(i); //这里的i是自由变量 }) document.body.appendChild(a); }
在上面的代码中,因为不知道什么时候才发生click事件,早就循环完毕,此时i已经是10了。
正确写法
var i ; for(i = 0; i < 10; i++){ (function(i){ var a = document.createElement("a"); a.innerHTML = i +"<br />"; a.addEventListener("click",function(e){ e.preventDefault(); alert(i); //这里的i是自由变量 }) document.body.appendChild(a); }(i); }
在for循环里面,包裹着一个子调用函数,把i传进去作为参数。
每次循环,i的值都不一样。最后达到预期效果。
3. 如何理解作用域
自由变量作用域链,即自由变量的查找
闭包的两个场景
相关文章推荐
- JS高级程序设计第四章笔记作用域&作用域链
- JS中的作用域和闭包
- js中作用域和闭包
- Js变量作用域闭包
- 关于JS变量的作用域,作用域链与闭包
- JS里面匿名函数的调用 & 变量作用域的实验
- js 中作用域、闭包的总结
- JavaScript&JQ 004_JS闭包
- JavaScript:Scope &Closure 变量作用域和闭包
- JS的的作用域和闭包
- js变量作用域,闭包。
- js 闭包以及就是变量作用域
- JS的作用域、闭包原理以及性能问题
- js加强:js引擎,变量作用域,arguments对象,特殊函数,闭包
- js的作用域、作用域链、闭包
- js闭包实现块级作用域和私有变量的访问
- JS变量作用域、闭包
- JavaScript高级程序设计(第2版) 学习笔记:(二)js函数作用域与闭包
- 【JavaScript】熟悉js的继承链,作用域,闭包
- JS中的作用域与闭包:this,var,(function () {})