媒介:
这是一篇关于闭包函数的总结和笔记
愿望对人人有点协助
写的不好的处所,也请人人多多指教
一: js中的定名函数,匿名函数,自挪用函数和回调函数
1.定名函数: 函数假如有名字,就是定名函数
function f1( ) {
console.log("我就是定名函数");
}
2.匿名函数: 函数假如没有名字,就是匿名函数
(function () {
console.log("我就是匿名函数");
})
3.自挪用函数: 本身挪用本身
var f2 = function () {
console.log("你好");
};
f2();
fn内里存储的是函数体代码,经由过程fn()的体式格局挪用. 匿名函数自挪用: 在匿名函数背面加括号,内里表面都能够; 也能够在函数前用 ! + -;
缘由:js只能辨认表达式(由运算符构成的式子) 与 语句( 顺序流程掌握 );让匿名函数能够挪用道理:将匿名函数变成表达式
4.回调函数: 回调函数就是一个参数将这个函数作为参数传到另一个函数内里当谁人函数实行完以后,再实行传进去的这个函数。
function f3(fn) {
fn(); //函数挪用 --- 申明fn这个变量中存储的是一个函数
};
function f4() {
console.log("函数能够作为参数运用")
}
f3(f4); // 挪用f3,将f4作为参数运用
二: 函数的语法
1.函数声明
function f5() {
console.log("我是函数声明");
};
f5()
2.表达式声明
var f6 = function () {
console.log("我是表达式声明");
};
f6();
三: 匿名函数的四种罕见场景
1.注册事宜
document.querySelector("#btn").onclick = function () {
console.log("我是匿名函数挪用的一种场景");
};
2.定时器
setInterval(function () {
console.log("我是定时器中的匿名函数");
},1000);
3.变量存储
var f7 = function () {
console.log("我是变量存储中的函数");
};
4.对象要领
var obj = {
name: "拉克丝",
say: function () {
console.log(this.name);
}
};
obj.say();
四: 闭包函数
闭包有三个特征: 函数嵌套函数; 函数内部能够援用外部的参数和变量; 参数和变量不会被渣滓接纳机制接纳
闭包的优点是:1.愿望一个变量历久驻扎在内存中 2.防止全局变量的污染 3.私有成员的存在
01 全局变量的累加
var a = 1;
function f7( ){
a++;
alert(a);
}
f7(); // 2
f7(); // 3
f7(); // 4
02 局部变量
function f8( ){
var a = 1;
a++;
alert(a);
}
f8(); // 2
f8(); // 2
f8(); // 2
03 局部变量的累加
function outer( ){
var x = 10;
return function ( ) {
//函数嵌套函数
x++;
alert(x);
}
}
//外部函数只挪用一次,获得的同一个变量
var y = outer(); //外部函数赋值给变量y 挪用一次外部函数,获得一个闭包函数
y(); // 11 //挪用闭包函数,返回内部变量
y(); // 12
y(); // 13
outer()(); // 11
outer()(); // 11
outer()(); // 11
04 典范例子
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
fn1() // 1 6
fn()() // 1 4
fn()() // 1 4
fn()() // 1 4
05 模块化代码,削减全局变量的污染
var abc = (function ( ) {
//abc 为外部匿名函数的返回值
var a = 1;
return function ( ) {
a++;
alert(a);
}
}());
abc(); // 2 // 挪用一次abc函数,实在就是挪用内里内部函数的返回值
abc(); // 3
abc() // 4
06 私有成员的存在
var aaa = (function ( ) {
var a = 1;
function bbb( ) {
a++;
alert(a);
}
function ccc( ) {
a++;
alert(a);
}
return {
b: bbb,
c: ccc
}
})();
aaa.b(); // 2
aaa.c(); // 3
aaa.b(); // 4
aaa.c(); // 5
07 运用匿名函数完成累加
运用匿名函数完成局部变量驻留在内存中,从而完成累加
function aaa( ) {
var a = 10;
return function ( ) { //匿名函数
a++;
return a;
};
}
var y = aaa();
alert(y()); // 11
alert(y()); // 12
alert(y()); // 13
08 闭包作为参数通报
var num = 15;
var fn1 = function (x) {
if(x > num){
console.log( x );
}
}
void function (fn2) {
var num = 100;
fn2(30);
}(fn1); // 30
// void 相当于匿名函数的自挪用
// fn2是当作参数传进来的 不是在void内里声明的 是在全局作用域里声明的 所以拿的是num=15 所以打印出来30
对上题有迷惑的,能够看下面这个
var num = 15;
var fn1 = function (x) {
if(x > num){
console.log( x ); // 30
}
}
void function (fn2) {
var num = 100;
fn2(30);
function fn3(x) {
console.log( num ); // 100
if(x < num){
console.log( x ); //30
}
}
fn3(30)
}(fn1);
闭包的运用场景
一.点击li标签,涌现对应的索引
<ul id="ul1">
<li>你好我是轮回闭包中的第0个</li>
<li>你好我是轮回闭包中的第1个</li>
<li>你好我是轮回闭包中的第2个</li>
<li>你好我是轮回闭包中的第3个</li>
<li>你好我是轮回闭包中的第4个</li>
</ul>
1.js中增加索引的做法
var ul1 = document.getElementById("ul1");
for(var i = 0; i < ul1.children.length; i++){
ul1.children[i].setAttribute("index",i);
ul1.children[i].onclick = function () {
console.log(this.getAttribute("index"))
}
};
2.jQuery中index做法
$(function () {
var index = null;
$("li").on("click",function () {
index = $(this).index();
console.log(index);
});
})
3.闭包的处置惩罚
var ul1 = document.getElementById("ul1");
//毛病的做法
function showLiNum(ul1) {
for(var i = 0; i < ul1.children.length; i++){
ul1.children[i].onclick = function () {
console.log(i);
}
}
}
showLiNum(ul1)
//当点击之前,轮回已完毕;所以i的值为别.children.length;
正解:应用一个闭包,竖立一个匿名函数;将每一个i存在内存中.onclick函数用的时刻提取出外部匿名函数的值
function showLiNum(ul1) {
for(var i = 0; i < ul1.children.length; i++){
(function (i) {
ul1.children[i].onclick = function () {
console.log(i);
}
}(i));
}
}
showLiNum(ul1)
也能够如许
function showLiNum(ul1) {
for(var i = 0; i < ul1.children.length; i++){
ul1.children[i].onclick = (function (i) {
return function () {
console.log(i);
}
}(i));
}
}
showLiNum(ul1);
二.定时器
开启定时器,离别打印1,2,3,4,5
毛病的写法:
for(var i = 1; i <= 5; i++){
setTimeout(function () {
console.log(i);
},1000)
}
准确写法
for(var i = 1; i <= 5; i++){
(function (i) {
setTimeout(function () {
console.log(i);
},i*1000);
}(i))
}
//相当于同时启动3个定时器,i*1000是为5个定时器离别设置了差别的时候,同时启动,
//然则实行时候差别,每一个定时器距离都是1000毫秒,完成了每隔1000毫秒就实行一次打印的结果。
典范面试题
最后上一道闭包中的典范面试题,假如你能弄懂这个,那申明闭包弄懂的差不多啦
var name = "The Window";
var obj = {
name : "The object",
getNameFunc : function(){
return function(){
return this.name;
}
}
}
alert( obj. getNameFunc()() )
var name = "The Window";
var obj = {
name : "The object",
getNameFunc : function(){
var that = this;
return function(){
return that.name;
}
}
}
alert( obj. getNameFunc()() )
javascript是动态(或许动态范例)言语,this关键字在实行的时刻才确定是谁。所以this永久指向挪用者,即对’挪用对象’的援用; “谁挪用,指向谁”。
第一部份实行代码object.getNameFunc()以后,返回了一个新的匿名函数,此时在全局作用域挪用匿名函数,它不在是object的属性或许要领,此时挪用者是window,因而输出是 The Window。
第二部份,当实行函数object.getNameFunc()后返回的是:function( ){return that.name;}此时的that=this。而this指向object,所以that指向object。他是对object的援用,所以输出The Object。
总结:关于js中的this,记着谁挪用,this就指向谁;要接见闭包的this,要定义个变量缓存下来。平常var that(_this) = this。