1. 匿名函数做参数
$(document).ready(funtction(){
$('div.poem-stanza').addClass('highlight');
});
可以外层函数中把内部函数赋值给外层变量或者全局变量,从而逃离作用域调用;
2. 闭包
既不是内部函数局部变量,也不是其参数的变量,成为自由变量;
外部函数的调用环境称为封闭闭包的环境。
(PS:直接调用内部函数时,自由变量和函数怎么来保存上下文?)
当内部函数在定义它的作用域的外部被引用时,就创建了一个该内部函数的闭包。
从本质上,如果内部函数引用了位于外部函数中的变量,相当于授权该变量能够被延迟使用。外部函数调用完成后,这些变量的内存没有释放,因为闭包环境还需要使用
(PS:到什么时候结束?所为自由变量的生命周期)
-----------------
console.log = function(message) {
$(document).ready(function() {
$('<div class="result"><div>')
.text(String(message))
.appendTo('#results');
});
};
function outerFn() {
var outerVar = 0;
function innerFn1() {
outerVar++;
console.log('(1) outerVar = ' + outerVar);
}
function innerFn2() {
outerVar += 2;
console.log('(2) outerVar = ' + outerVar);
}
return {'fn1': innerFn1, 'fn2': innerFn2};
}
var fnRef = outerFn();
fnRef.fn1();
fnRef.fn2();
fnRef.fn1();
var fnRef2 = outerFn();
fnRef2.fn1();
fnRef2.fn2();
fnRef2.fn1();
-------------
通过对象返回两个函数,通过二级指定调用;下面是执行结果:
(1) outerVar = 1
(1) outerVar = 3
(1) outerVar = 4
(2) outerVar = 1
(2) outerVar = 3
(2) outerVar = 4
3. 立即调用模式
-------------
$(document).ready(function() {
for (var i = 0; i < 5; i++) {
(function(value) {
$('<div>Print ' + value + '</div>')
.click(function() {
console.log(value);
}).insertBefore('#results');
})(i);
}
});
-------------
4.闭包引起的内存释放困难
-------------
function outerFn() {
var outerVar = {};
function innerFn() {
console.log('hello');
}
outerVar.fn = innerFn;
return innerFn;
};
-------------
innerFn的闭包环境中默认会包含outerFn中的变量outerVar,但是outerVar又指向了innerFn;
垃圾回收器不能明确知道这种循环的指向什么时候释放
5.老版本IE中DOM和JS的对象由不同的内存管理程序负责;
当一个循环同时包含DOM元素和JS常规对象,就会引发这种循环;
-------------
$(document).ready(function() {
var button = document.getElementById('button-1');
button.onclick = function() {
console.log('hello');
return false;
};
});
-------------
click事件会创建封闭环境包含button变量的闭包,而button又包含一个指向闭包的引用onclick属性本身;这种死锁内存要关闭浏览器才能释放。
可以避免闭包环境包含引用变量:
-------------
function hello() {
console.log('hello');
return false;
}
$(document).ready(function() {
var button = document.getElementById('button-1');
button.onclick = hello;
});
-------------
或者用jQuery结构的时间绑定方法
-------------
$(document).ready(function() {
var $button = $('#button-1');
$button.click(function(event) {
event.preventDefault();
console.log('hello');
});
});
-------------
虽然也有闭包,但是jQuery会手动释放自己制定的所有事件处理程序。
除了事件之外的循环仍然会触发内存泄露
.data()方法可以作为替代方案;