1.作用域: 什么是?
域表示范围,即是作用范围(包括局部作用域和全局作用域)
作用域规则?
1.函数内允访问函数外的数据,反之不行
2.整个代码结构中只有函数可以限定作用域
3.作用规则首先使用提升规则分析
4.如果当前作用规则中可以找到,就不会到外面找
2.关于变量提升 即解析器会把函数声明和变量声明提升到前面。这里注意一下函数声明和表达式的区别,若是函数表达式,则提升的不是函数体,而是声明的函数名。
foo();
//foo is not a function,会把var foo提升到前面,但是函数体没有提升
foo1();
//1,会把函数提到前面
console.log(a);
//undefined,变量提升会将var a提升到前面,但是还没有赋值
var foo=function(){
console.log(1);
};
//函数表达式
function foo1(){
console.log(1);
};
//函数表达式
var a=10;
3.关于作用域链 什么是?
只有函数可以产生作用域,主要是代码,至少有一个作用域,即全局作用域。凡是代码中有函数,那么函数就构成另一个作用域,如果函数还有函数,那么再在这个作用域中有产生一个作用域,那么将是这些所有列出来,可以有一个有函数内想函数外的链式结构。
作用域链的绘制
1.将全局看作一条链,即顶级链,记为0级
2.看全局作用域中有什么成员,就绘制到0级链上(看声明)
3.再找函数,只有函数可以限制作用域,因此只有函数菜可以引出一条新链,按照1、2…顺序依次绘制
var num=12;
function f1(){
var num=123;
function f2(){
console.log(num);
}
}
上面代码的作用域链如下:
文章图片
变量的访问规则
1.若要使用变量,首先再本作用域链上找,如果有则直接使用
2.若没有,则往上一级找,若有直接使用,若还是没有,再往上找,直到全级链还是没有,就报错。另外:需注意,同一级的链无法访问。
4.关于闭包 什么是?
函数和其词法环境一起构成闭包,即可使函数再当前作用域作用域范围之外执行。
***作用***可读取函数内部的变量,可以使变量的值长期保存再内存中,生命周期较长,可用来实现js模块。
//使用闭包实现模块化
function myCounter() {
var num = 0;
function optionNum(val) {
num += val;
}
var obj={
addNum: function(){
optionNum(1);
},
subNum:function(){
optionNum(-1);
},
value:function(){
return num;
}
}
return obj;
}
var counter=myCounter();
counter.addNum();
console.log(counter.value());
} //函数的防抖也应用到了闭包
//运用单例模式模仿在一个页面中只能有一个登录框的效果,其中也用到了闭包
class LoginForm{
constructor(){
this.state='hiden'
}
show(){
if(this.state==='hiden'){
console.log('对话框显示');
this.state="show";
}else{
alert("对话框已经显示,无法同时显示两个")
}
}
hide(){
if(this.state==='show'){
console.log('对话框隐藏');
this.state='hiden';
}else{
alert('对话框已经隐藏,无法再次隐藏');
}
}
}
LoginForm.getLoginForm=(function(){
let instance;
return function(){
if(!instance){
instance=new LoginForm();
}
return instance;
}
})();
let login1=LoginForm.getLoginForm();
login1.show();
let login2=LoginForm.getLoginForm();
login2.show();
【作用域链和闭包】闭包的一个错误使用
文章图片
以上代码来源:添加链接描述
闭包性能问题:
函数执行需要内存,那么函数中定义的变量,会在函数执行结束后自动回收。凡是闭包结构被引出的数据,如果还有变量引用这些数据,则这些数据就不会被回收(如:当一个变量为一个dom节点获取或者宿主对象,它的一个属性(onclick…)引用一个内部函数,而内部函数又在引用外部对象。会造成互相引用,引起内存泄露。)因此,在使用闭包的时候,若不使用某些数据,一定要赋值null
var f=(function(){
var num=123;
return function(){
return null;
}
})();
//f引用函数,函数引用变量
//因此,在不使用该数据时,最好写上f=null
推荐阅读
- 操作系统|[译]从内部了解现代浏览器(1)
- web网页模板|如此优秀的JS轮播图,写完老师都沉默了
- JavaScript|vue 基于axios封装request接口请求——request.js文件
- vue.js|vue中使用axios封装成request使用
- JavaScript|JavaScript: BOM对象 和 DOM 对象的增删改查
- JavaScript|JavaScript — 初识数组、数组字面量和方法、forEach、数组的遍历
- JavaScript|JavaScript — call()和apply()、Date对象、Math、包装类、字符串的方法
- JavaScript|JavaScript之DOM增删改查(重点)
- javascript|vue使用js-xlsx导出excel,可修改格子样式,例如背景颜色、字体大小、列宽等
- javascript|javascript中的数据类型转换