// 第一种
(function(){
})(); // 看着清晰
// 第二种
(function(){
}()); // W3C建议
// 第三种
+function test(){
}()
// 1、简单示例
// 用括号包裹匿名函数:因为括号包裹的是函数表达式,前后需要加分号
(function(){
var a = 1;
var b = 2;
console.log(a + b); // 3
}());
// 2、参数问题
(function(a, b){ // 形参
console.log(a + b); // 3
}(1, 2)); // 实参
// 3、返回值:用变量接受表达式
var num = (function(a, b){
return a + b;
}(1, 2));
console.log(num); // 3
(1)括号包起来的一定是表达式
(funiton test(){})
(2)一定是表达式才能被执行符号执行
// 被执行
(function test1() {
console.log(1); // 1
})();
// 被执行
var test2 = function() {
console.log(1); // 1
}();
// 不传参报错,不是一个表达式,原因:JS引擎认为不传参数就是不是表达式
// 报语法错误:Uncaught SyntaxError: Unexpected token )
function test3() {
console.log(1);
}(); // 没传参
// 传入参数不报错,但不执行,原因:JS引擎认为传了参数就是表达式
function test5(a) {
}(6); // 传入参数
(3)立刻执行函数:自动执行、执行完成以后立刻释放
// 括号包裹-会报错
(function test(){
var a = 1;
var b = 2;
console.log(a + b); // 3
}());
// 因为执行完毕即可销毁,外部调用不到test函数
console.log(test()); // Uncaught ReferenceError: test is not defined
// 表达式-不会报错
var test1 = function() {
console.log(2); // 2
}();
console.log(test1); // undefined
(4)如果函数变为表达式,函数名就会被忽略
// 匿名函数
var num = (function(){
return 123;
})();
console.log(num); // 123
// 忽略函数名
var num = (function test(){
return 123;
})();
console.log(num); // 123
(5)函数声明变为表达式的方法,在表达式前加 +、-、!、||、&&
// 1、函数声明:function test(){}
// 2、函数声明变为表达式(前面加符号):+function test(){}
// 3、表达式立刻执行(末尾加括号):+function test(){}()
+function test() {
console.log(1);
}();
1 && function test() {
console.log(1);
}();
(1)window与return的闭包返回
// window与return:作用一样
function testCal() {
var a = 1;
function plus() {
a++;
console.log(a);
}
// window.plus = plus;
return plus;
}
var plus = testCal();
plus(); // 2
plus(); // 3
plus(); // 4
(2)插件写法
//外层匿名函数包裹:隔离作用域,防止全局函数和变量污染
// 防止出错,默认加分号,变成表达式
(function(){
function Test() {
}
window.Test = Test;
})();
// 调用
var test = new Test();
// 更好的写法:默认前面加分号
;(function(){
function Test() {
}
window.Test = Test;
})()
// 调用
var test = new Test();
function test() {
var arr = [];
for(var i = 0; i < 10; i++) {
// 赋值语句,系统定义的时候为函数引用,访问不到里面的值
// 只有在外部执行的时候才会看到里面的i值
arr[i] = function() { // 匿名函数
document.write(i + ' ');
}
}
// for循环 等价
// var i = 0;
// for(; i < 10; ) {
// arr[i] = function() {
// document.write(i + ' ');
// }
// i++;
// }
return arr;
}
var myArr = test();
console.log(myArr); // 10个匿名函数 [ƒ, ƒ, ƒ, ƒ, ƒ, ƒ, ƒ, ƒ, ƒ, ƒ]
for(var j = 0; j < 10; j++) {
myArr[j](); // 10 10 10 10 10 10 10 10 10 10
}
// 答案: 10个10
// 原因:
// 1、test中的for循环,在arr中存放了10个匿名函数,但是没执行
// 2、当for循环完毕之后,test函数中AO存放的i变量已经变为了10
// 3、当return arr的时候,形成了10个闭包,即10个匿名函数,虽然test的AO被销毁,但是返回的每个匿名函数中都有test的AO
// 4、当在外部for循环调用每个匿名函数的时候,输出的i都是10
如果想打印0-9,的解决方法:
// 第一种方法:需要立刻执行函数
function test() {
//var arr = [];
for(var i = 0; i < 10; i++) {
// 改为立刻执行函数
(function() {
document.write(i + ' ');
}());
}
//return arr;
}
test();
// 第二种方法:外部传入
function test() {
var arr = [];
for(var i = 0; i < 10; i++) {
arr[i] = function(num) {
document.write(num + ' ');
}
}
return arr;
}
var myArr = test();
console.log(myArr); // [ƒ, ƒ, ƒ, ƒ, ƒ, ƒ, ƒ, ƒ, ƒ, ƒ]
for(var j = 0; j < 10; j++) {
myArr[j](j); // 0 1 2 3 4 5 6 7 8 9
}
// 第三种方法:立刻执行保存值(最常用)
function test() {
var arr = [];
for(var i = 0; i < 10; i++) {
// 实际循环立刻执行函数:立刻执行函数保存i值
(function(j){
// 立即执行函数AO中的 j = 0, 1, 2, 3......
// 每个立刻执行函数中都有一个唯一的j值
arr[j] = function() {
// 访问的是立刻执行函数AO中的j值:0, 1, 2....
document.write(j + ' ');
}
})(i);
}
return arr;
}
var myArr = test();
console.log(myArr); // [ƒ, ƒ, ƒ, ƒ, ƒ, ƒ, ƒ, ƒ, ƒ, ƒ]
for(var j = 0; j < 10; j++) {
myArr[j](); //0 1 2 3 4 5 6 7 8 9
}
点击li的数字打印出对应的数字值
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Demo列表</title>
<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
<script type="text/javascript">
var oLi = document.querySelectorAll('li');
for (var i = 0; i < oLi.length; i++) {
// 每次点击都是5
// oLi[i].onclick = function() {
// console.log(i);
// }
// 立刻执行函数包裹解决
(function(j){
oLi[j].onclick = function() {
console.log(j + 1);
}
})(i);
}
</script>
</body>
</html>
// 逗号运算:返回最后一个
var num = (2 - 1, 6 + 5, 24 + 1);
console.log(num); // 25
var fn = (
function test1() {
return 1;
},
function test2() {
return '2';
}
)();
// 1、括号中有逗号,返回执行的是test2函数,
// 2、然后立即执行,又return '2',最后返回为字符串2
console.log(fn); // '2'
console.log(typeof fn); // 'string'
var a = 10;
if (function b(){}) { // 函数声明为true
// 因为b函数声明被括号括起来了,所以(function b(){})为表达式,忽略了函数名b,所以没有b
a += typeof(b); // 因为b没有,所以typeof b为'undefined'
}
console.log(a); // '10undefined'