执行上下文
变量定义 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 + '<br>';
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 + '<br>';
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