准备知识
词法环境:
词法环境 是定义在词法阶段的作用域,即是 函数声明、变量声明的位置所决定的。
就是 声明函数和变量的当前作用域
全局作用域和局部作用域和块作用域
1.全局作用域:var 关键字 在函数外声明的 所有变量都是 全局作用域的变量,
2.局部作用域:函数内部的变量 属于局部作用域,只能在函数内部访问
3.块作用域:是es6新增的一个概念
{} 中括号即形成一个块级作用域
ES6 可以使用 let 关键字或者 const 关键字来实现块级作用域
闭包定义
定义:闭包不单单是一个函数,这个(能够访问其他函数内部变量的)函数
连同其对词法环境的引用 捆绑在一起构成了闭包.
它像是一个桥梁,从函数外部能够访问到函数内部。
code
var a = 1
function fn(){
var b = 2 //局部作用域
}
console.log(window.a); //1
console.log(b); // b is not defined
/*
由于没有构造闭包,所以b无值
*/
闭包的作用与缺点
作用:
1)能够读取函数函数内部变量
2)让这些变量始终保持在内存中,不会再函数被调用后被自动清除。
3)避免全局变量的污染
缺点:
1)闭包使得函数中的变量保存在内存中,内存消耗很大。所有不能滥用。在IE中导致内存泄漏。
2)闭包会在父函数外部,改变父函数内部变量的值。慎用,不要随便改变
function makeFunc(){
var name = 'maktub';
function displayName(){
alert(name);
}
return displayName;
//形成词法环境
}
var myFunc = makeFunc();
//myFunc 引用了函数makeFunc 阻止了name 被回收 而且访问到了 函数内部的变量name
myFunc(); //alert('maktub')
小白:下面这是一个闭包吗?会输出什么?
function f( x ){
var a = [];
for ( var i = 0; i < x.length; i ++ ){
var temp = x[i];
a.push( function(){
alert( temp + ' ' + x[i] )
});
}
return a;
}
function e(){
var a = f( ["a", "b", "c"] );
for ( var i = 0; i < a.length; i ++ ){
a[i]();
}
}
e(); // 调用函数e
结果:自行运行
是一个闭包。function里面引用了temp i 变量 ,只是闭包中的变量temp和i 并不是固定的,它会随时根据函数运行环境中的变量的值变化而更新
小白:如果我想要按照 a b c 输出怎么做?
function f( x ){
var a = [];
for ( var i = 0; i < x.length; i ++ ){
var temp = x[i];
a.push(
(function(temp, i ){
return function(){
alert( temp + ' ' + x[i] )
}
})(temp,i)
);
}
return a;
}
function e(){
var a = f( ["a", "b", "c"] );
for ( var i = 0; i < a.length; i ++ ){
a[i]();
}
}
e(); // 调用函数e
小白:有更简单的方式吗?
小黑:当然, for循环 声明 i 跟temp 的时候
利用es6中的let也是可以的
code
function f( x ){
var a = [];
for ( let i = 0; i < x.length; i ++ ){
let temp = x[i];
a.push( function(){
alert( temp + ' ' + x[i] )
});
}
return a;
}
function e(){
var a = f( ["a", "b", "c"] );
for ( var i = 0; i < a.length; i ++ ){
a[i]();
}
}
e();
闭包的应用场景
- 回调函数 会形成闭包
function makeFunc(fn){
let num = 1;
// console.log(num);
return setTimeout(() => {
fn(num)
}, 1000);
}
function callback(number){
console.log(++number);
}
makeFunc(callback)//2
- 实际应用场景:实现商品的价格,点击量排序
let lessons = [
{
titel:'qqq',
price:120,
click:100
},
{
titel:'aaa',
price:43,
click:230
},
{
titel:'sss',
price:12,
click:80
},
{
titel:'fff',
price:1,
click:233
},
];
let table1 = lessons.sort(function(a,b){
return a.price > b.price ? 1: -1;
})
console.table(table1)
let table2 = lessons.sort(function(a,b){
return a.click > b.click ? 1: -1;
})
console.table(table2)
上面这种代码复用率不高,看看闭包的方式
function order(field,type = "asc"){
return function(a,b){
if(type == "desc") return a[field] > b[field] ? -1 : 1;
return a[field] > b[field] ? 1 : -1;
}
}
let table1 = lessons.sort(order('price'))
console.table(table1);
let table2 = lessons.sort(order('price','desc'))//降序
console.table(table2);
链接
后盾人 ,推荐,适合入门的前端。
综上,另外sort 会在以后的ES6详细整理。
全力以赴奔向你le。