/*
* 下面代码是否可以,每隔1000MS依次输出 0 1 2 3 4 5 ?
* 如果不可以,说明为啥?
* 以及如何解决?
*/
/*
// 不行:基于var在循环中声明的变量“i”是全局变量
// 第一轮循环 全局i=0 设置第一个定时器{1000} 给定时器设置的回调函数并没有执行,等待1秒后执行,循环继续
// 第二轮循环 全局i=1 设置第二个定时器{2000}
// ...
// 第五轮循环 全局i=4 设置第五个定时器{5000} i++,让全局的i=5,循环结束
// ->每一个定时器设置的回调函数,只有等到循环结束后,到了等待的时间,才会触发执行
for (var i = 0; i < 5; i++) {
setTimeout(function () {
/!*
* EC(AN)
*
* 作用域链:<EC(AN),EC(G)>
* 形参赋值:--
* 变量提升:--
*!/
console.log(i); //i不是自己私有的,是全局的,但是此时全局的i已经是循环结束后的5了
}, (i + 1) * 1000);
}
*/
//=======解决方案:闭包
/*
第一轮 全局i=0
(function (i) {
// EC(AN1) 私有i=0 闭包
setTimeout(function () { //0x001 [[scope]]:EC(AN1)
console.log(i);
}, 1000);
})(0);
第二轮 全局i=1
(function (i) {
// EC(AN2) 私有i=1 闭包
setTimeout(function () { //0x002 [[scope]]:EC(AN2)
console.log(i);
}, 2000);
})(1);
....
循环结束:设置了五个闭包,每一个闭包中都有一个自己的私有变量“i”,存储的值分别是0~4;全局i是5;
*/
// for (var i = 0; i < 5; i++) {
// (function (i) {
// setTimeout(function () {
// console.log(i);
// }, (i + 1) * 1000);
// })(i);
// }
// var fn = function fn(i) {
// return function () {
// console.log(i);
// };
// };
// for (var i = 0; i < 5; i++) {
// // 第一轮 全局i=0 设置定时器{1000}
// // + fn(0) EC(FN1) 私有i=0 返回一个小函数0x001
// // + setTimeout(0x001,1000)
// setTimeout(fn(i), (i + 1) * 1000);
// }
// // new Array(5).fill(null) 创建一个长度为5的数组,每一项填充null,把其变为密集数组,这样可以forEach
// // “_”就是形参占位,原本应该有个形参变量,但是我不想用,所以我占个位即可
// new Array(5).fill(null).forEach(function (_, index) {
// // 第一轮 EC(AN1) index=0 设置定时器{1000} 闭包
// // 第二轮 EC(AN2) index=1 设置定时器{2000} 闭包
// // ...
// setTimeout(function () {
// console.log(index);
// }, (index + 1) * 1000);
// });
// 真实项目中都这样搞
// for (let i = 0; i < 5; i++) {
// setTimeout(function () {
// console.log(i);
// }, (i + 1) * 1000);
// }
//====终极方案:基于定时器传参「核心:闭包」
// for (var i = 0; i < 5; i++) {
// setTimeout(function (i) {
// console.log(i);
// }, 1000, i);
// }
//=========
/* setTimeout(function (x) {
// 等待1秒后,浏览器帮助我们把这个函数执行
// + 当前写法是没有给其传实参值的,所以x的值是undefined
}, 1000); */
/* // 设置定时器的时候:第一个是回调函数CB、第二个是等待时间
// 第三个及以后都是到时间后,执行CB,给CB预先传递的实参值
setTimeout(function (x, y) {
console.log(x, y); //1秒后执行回调函数,x='zhufeng' y='peixun'
}, 1000, 'zhufeng', 'peixun'); */
//=====================================================
// 问题:全局变量污染
/* var name = '曹雅倩';
var age = 18;
var BF = false;
var name = "李利颖";
var age = 62;
var BF = true; */
// 解决1:闭包
/* (function () {
var name = '曹雅倩';
var age = 18;
var BF = false;
})();
(function () {
var name = "李利颖";
var age = 62;
var BF = true;
})(); */
// 解决2:对象
// 把描述同一事物的属性和方法放在一起,实现了分组的效果,避免了全局变量的污染;每一个对象都是一个单独的实例(个体/堆内存空间),所以我们把这种方案称之为“单例设计模式”!!
// person1:命名空间 namespace
/* var person1 = {
name: '曹雅倩',
age: 18,
BF: false
};
var person2 = {
name: '李利颖',
age: 62,
BF: true
}; */
//----
// 资讯板块
var newsModule = (function () {
var box = null;
var query = function query() {};
// 需求:把这个私有的方法setVal,在其它板块中使用
var setVal = function setVal() {};
// 解决1:直接挂载到GO中「弊端:挂载的东西多了,很可能有引发全局变量污染」
window.setVal = setVal;
// 解决2:基于返回值,返回一个对象(命名空间),里面包含需要供外部调用的属性和方法即可
return {
setVal: setVal,
query: query
};
})();
// 换肤板块
var skinModule = (function () {
var box = null;
var query = function query() {};
setVal();
return {};
})();
// 搜索板块
var searchModule = (function () {
var query = function query() {};
newsModule.setVal();
return {};
})();