贵阳白云区城乡建设局网站,app分销系统开发,做简单网站后端需要学什么,新乐做网站优化js里面的闭包是一个难点也是它的一个特色#xff0c;是我们必须掌握的js高级特性#xff0c;那么什么是闭包呢#xff1f;它又有什么作用呢#xff1f;
1#xff0c;提到闭包我们这里先讲解一下js作用域的问题
js的作用域分两种#xff0c;全局和局部#xff0c;基于我…js里面的闭包是一个难点也是它的一个特色是我们必须掌握的js高级特性那么什么是闭包呢它又有什么作用呢
1提到闭包我们这里先讲解一下js作用域的问题
js的作用域分两种全局和局部基于我们所熟悉的作用域链相关知识我们知道在js作用域环境中访问变量的权利是由内向外的内部作用域可以获得当前作用域下的变量并且可以获得当前包含当前作用域的外层作用域下的变量反之则不能也就是说在外层作用域下无法获取内层作用域下的变量同样在不同的函数作用域中也是不能相互访问彼此变量的。
1变量在函数内声明变量为局部作用域。 局部变量只能在函数内部访问。
// 此处不能调用 carName 变量
function myFunction() {var carName Volvo;// 函数内可调用 carName 变量
}2变量在函数外定义即为全局变量。 全局变量有 全局作用域: 网页中所有脚本和函数均可使用。
ar carName Volvo;
// 此处可调用 carName 变量
function myFunction() {// 函数内可调用 carName 变量
}3如果变量在函数内没有声明没有使用 var 关键字该变量为全局变量。 以下实例中 carName 在函数内但是为全局变量。
// 此处可调用 carName 变量
function myFunction() {carName Volvo;// 此处可调用 carName 变量
}2闭包有3个特性
①函数嵌套函数
②函数内部可以引用函数外部的参数和变量
③参数和变量不会被垃圾回收机制回收
3闭包存在两种的主要形式
1、函数作为返回值
function fn(){var str abc;return function(){return str}
}
var fn1 fn();
console.log(fn1) //abc在这段代码中fn()中的返回值是一个匿名函数这个函数在fn()作用域内部所以它可以获取fn()作用域下变量str的值将这个值作为返回值赋给全局作用域下的变量fn1,实现了在全局变量下获取到局部变量中的变量的值
2、经典闭包循环
function fn(){var num 3;return function(){var n 0;console.log(n);console.log(num);}
}
var fn1 fn();
fn1(); //1 4
fn1()//1 5一般情况下在函数fn执行完后就应该连同它里面的变量一同被销毁但是在这个例子中匿名函数作为fn的返回值被赋值给了fn1这时候相当于fn1function(){var n 0 … }并且匿名函数内部引用着fn里的变量num所以变量num无法被销毁而变量n是每次被调用时新创建的所以每次fn1执行完后它就把属于自己的变量连同自己一起销毁于是乎最后就剩下孤零零的num于是这里就产生了内存消耗的问题
3、定时器与闭包
for(var i0;i5;i){setTimeout((){console.log(i,000)},100)
} for(var i0;i5;i){(function(i){setTimeout((){console.log(i,000)},100)})(i)
}引入闭包来保存变量i将setTimeout放入立即执行函数中将for循环中的循环值i作为参数传递100毫秒后同时打印出1 2 3 4 5
4、闭包作为参数传递 var num 10
var fn function (x) {if (xnum) {console.log(x, num值)}
}
void function (fn1) {var num 100fn1(30)
}(fn)拓展一下参数传递
1.1参数传递方式
函数参数的传递方式有两种一个是传值传递一个是传址传递。
当函数参数是原始数据类型时字符串数值布尔值参数的传递方式为传值传递。也就是说在函数体内修改参数值不会影响到函数外部。
var a 1;
function keith(num) {
num 5;
}
keith(a);
console.log(a); //1上面代码中全局变量a是一个原始类型的值传入函数keith的方式是传值传递。因此在函数内部a的值是原始值的拷贝无论怎么修改都不会影响到原始值。
但是如果函数参数是复合类型的值数组、对象、其他函数传递方式是传址传递pass by reference。也就是说传入函数的是原始值的地址因此在函数内部修改参数将会影响到原始值。
var arr [2, 5];
function keith(Arr) {
Arr[0] 3;
}
keith(arr);
console.log(arr[0]); //3上面代码中传入函数keith的是参数对象arr的地址。因此在函数内部修改arr第一个值会影响到原始值。
注意如果函数内部修改的不是参数对象的某个属性而是替换掉整个参数这时不会影响到原始值。
var arr [2, 3, 5];
function keith(Arr) {
Arr [1, 2, 3];
}
keith(arr);
console.log(arr); // [2,3,5]上面代码中在函数keith内部参数对象arr被整个替换成另一个值。这时不会影响到原始值。这是因为形式参数Arr与实际参数arr存在一个赋值关系。
1.2同名参数
如果有同名参数则取最后面出现的那个值如果未提供最后一个参数的值则取值变成undefined。
function keith(a, a) {
return a;
}
console.log(keith(1, 3)); //3
console.log(keith(1)); //undefined如果想访问同名参数中的第一个参数则使用arguments对象。
function keith(a, a) {
return arguments[0];
}
console.log(keith(2)); //2