JS作用域和闭包

执行上下文

变量定义 var a= 100
函数声明 function fn1(){}
函数表达式 var fn1 = function(){}

在一个作用域内,会先定义变量和函数声明。但在执行变量声明和函数表达式时,会先声明这个变量,然后赋值为undefined,再按代码顺序执行。

var  a = 100;
fn1();
function  fn1(){}
fn2();
var fn2 = function(){}

代码的执行顺序是

var  a = undefined;
function fn1(){}
var fn2 = undefined;
fn1();
fn2();
fn2 = function(){}

this

this要在执行时才能确认值,定义时无法确认

this的使用场景

作为构造函数执行

function Foo(name){
     // this = {};
     this.name = name;
     // return this;
}
var f = new Foo();

作为对象属性执行
做为普通函数执行

function fn(){ console.log(this); }    //this === window
fn();

改变this的三个函数:call apply bind

function fn1(name){ console.log(this); }

fn1.call({num:100}, 'zhangsan');       //this === {num: 100}     最常用
fn1.apply({num:100}, ['zhangsan']);  //与call的区别是传递参数的方式不一样

var fn2 = function(name){
     console.log(this);          //this ===  {aa:100}
}.bind({aa:100});                //bind只能用函数表达式,不能用函数声明

fn2('zhangsan');

作用域

没有块级作用域
只有函数和全局作用域
当前作用域没有定义的变量,即“自由变量”

闭包

闭包的使用场景

函数做为返回值
function f1(){
     var a = 100;
     return  function (){ console.log(a); }          // a是自由变量,父作用域寻找
}
var f = f1();
var a = 200;
f();
函数做为参数传递
var a = 100;

function f1(){
     return  function (){ console.log(a); }          // a是自由变量,只从声明变量的父作用域寻找,跟执行的作用域无关
}
var f = f1();

function f2(fn){
     var a = 200;
     fn();
}

f2(f);

解题

说一下对变量提升的理解

变量定义
函数声明(注意和函数表达式的区别)

创建10个a标签,点击的时候弹出来对应的序号
var i, a
for(i=0; i<10; i++){
     a = document.createElement('a');
     a.innerHTML = i + '
'; a.addEventListener('click', function(e){ e.preventDefault(); alert(i) //无论点哪个都会显示10 }) document.body.append(a); } //正确做法 for(i=0; i<10; i++){ (function(i){ a = document.createElement('a'); a.innerHTML = i + '
'; a.addEventListener('click', function(e){ e.preventDefault(); alert(i) }) document.body.append(a); })(i) }
如何理解作用域

自由变量
作用域链, 即自由变量的查找
闭包的两个场景

实际开发中闭包的应用
//闭包实际开发中主要用于封装变量, 收敛权限

function isFirstLoad(){
     var _list = [];

     return function(num){
          if(_list.indexOf(num) >= 0){
               return false;
          }else{
               _list.push(num);
               return true;
          }
     }
}

var firstLoad = isFirstLoad();
firstLoad(10)  //true
firstLoad(10)  //false
firstLoad(20)  //true
firstLoad(20)  //false

你可能感兴趣的:(JS作用域和闭包)