前言:作用域是js中一个非常基础的知识,也是前端面试题喜欢考察的地方。同时理解作用域也是使用闭包的一个前提。
作用域的理解
1、首先要理解js中没有块级作用域,js只有全局作用域和函数作用域;
- 没有在函数体里面声明的变量都是全局的
- 没有使用var 声明的变量都是全局的
2、然后我们要明白:作用域查找时,是查找定义时的作用域,而不是运行时的作用域
var a=;
function fn(){
var a=;
console.log('fn',a);
}
console.log('global',a);//200
fn();//100
3、this的使用,this和作用域有着很大的不同:this指向的是调用时的对象,而不是定义时的对象;
var wang={
name : "对象内部",
fn : function fn(){
console.log(this.name);
}
};
wang.fn();//对象内部
//使用call改变其作用域,使this指向call里面的对象
wang.fn.call({name:"改变作用域"});
类似call的函数还要apply、bind
apply的用法和call差不多,这里介绍一下bind的用法
var fn2=function(name){
alert(name);
console.log(this);
}.bind({y:}); //bind(obj)这个方法,将this转变为指向obj 即this=obj
fn2('zhangsan');
4、现在了解上面的知识之后,我们开始讲闭包;
闭包:就是一个函数内部的那个函数,可以在外部用来访问函数内部数据,防止数据被污染(阮一峰的解释为:闭包就是能够读取其他函数内部变量的函数。)
eg:写一个函数判断数据是否是第一次出现
function isFirstLoad() {
var _list=[];//将数组定义在内部,可以有效的避免数据的污染
return function(id){
if(_list.indexOf(id) === -){
_list.push(id);
console.log(_list);
return true;
}else{
return false;
}
}
}
var FirstLoad=isFirstLoad();
console.log(FirstLoad());//true
console.log(FirstLoad());//false
console.log(FirstLoad());//true
console.log(FirstLoad());//fasle
理解闭包之后,我们再讲闭包的使用场景
- 作为函数返回
function F1(){
var a=;
return function(){
console.log(a);
}
}
var f1=F1()
var a=;
f1();//100
- 作为函数传参
function F1(){
var a=;
return function(){
console.log(a);
}
}
var f1=F1()
function F2(fn){
var a=;
fn();
}
F2(f1)//100