閉包與迴圈中的函式
阿新 • • 發佈:2018-12-19
1.es5中的函式迴圈遍歷
由於在es5中沒有塊級作用域,會導致一些問題
//迴圈中的函式
var func = []; //這是個陣列
for(var i=0;i<10;i++){
console.log(i);//列印了0-9,這個時候i=10;,不小於10,迴圈遍歷結束
func.push(function () {
console.log(i);
console.log(1)
});//把數字放到陣列當中
}
console.log('迴圈遍歷完',i);// 迴圈遍歷完,這個時候是10
func.forEach(function (func) {
// console.log(2);
// func();
// console.log(func); //func代表的是function () {console.log(i)}
});
2.解決辦法是需要用到函式自執行的特性
var funcs = [];
//按程式從上至下的執行,先執行for迴圈,得到i等於10,
//然後foreach進行迴圈遍歷,執行函式呼叫,列印i的值
//所以列印了10個10
for(var i=0;i<10;i++){
console. log('迴圈遍歷列印',i); //迴圈遍歷列印
funcs.push(function (value) {
console.log('函式呼叫前:',value);
//把值給返回回來
return function () {
console.log('函式自呼叫後',value);
}
}(i)) //把i的值傳參給value
}
funcs.forEach(function (func) {
console. log(4);
func()
});
3.如果使用es6語法進行宣告變數,就可以避免出現這個問題
//如果用let宣告變數,則可以避免前面的問題 for of for in
//let 宣告使得每次迭代都會建立一個變數 i,
// 所以迴圈內部建立的函式會獲得各自的變數 i 的拷貝。
//每份拷貝都會在每次迭代的開始被建立並被賦值。
var funcss = [];
for(let i=0;i<10;i++){
funcss.push(function () {
console.log('let宣告變數',i); //0-9
});
}
funcss.forEach(function (func) {
func()
})
三、函式的新增特性
//預設引數對arguments物件的影響
//在es5,arguments總是能反映命名引數的變化
//預設引數對arguments物件的影響
//在es5,arguments總是能反映命名引數的變化
function foo(a,b) {
console.log(arguments[0] === a);//true
console.log(arguments[1] === b);//true
a =10;
b = 20;
console.log(arguments[0] === a);//true
console.log(arguments[1] === b);//true
}
foo(1,32);
function foo(a, b) {
//嚴格模式
"use strict"
console.log(arguments[0] === a); //true
console.log(arguments[1] === b); //true
a = 10;
b = 20;
console.log(arguments[0] === a); //false。 修改a的值不會影響到arguments[0]的值
console.log(arguments[1] === b); //false
}
foo(1, 2);
//用了es6語法特性
function foo(a, b = 30) {
console.log(arguments[0] === a); //true
console.log(arguments[1] === b); //true
a = 10;
b = 20;
console.log(arguments[0] === a); //false。 由於b使用了預設值。雖然a沒有使用預設值,但是仍然表現的和嚴格模式一樣。
console.log(arguments[1] === b); //false。 b使用了預設值,所以表現的和嚴格模式一樣。
}
foo(1, 2);
//預設引數表示式
function getValue() {
return 5;
}
function add(first, second = getValue()) { //表示使用getValue這個函式的返回值作為second的預設值。
return first + second;
}
console.log(add(1, 1)); // 2. 呼叫add函式的時候,傳入了第二個引數,則以傳入的引數為準。
console.log(add(1)); //getValue為5 // 6。 呼叫add函式的時候,沒有傳入第二個引數,則會呼叫getValue函式。
//未命名引數問題
function hu(a,...b) {
console.log(a);
console.log(b);
}
hu(1,2,3,4,5);
//函式中的擴充套件運算子
let values = [25,30,40,50,70];
console.log(Math.max(...values));//70 //相當於拆解陣列,使用擴充套件運算子
console.log(Math.max(...values,200));//200
四、箭頭函式
//箭頭函式
// (形參列表)=>{
// //函式體
// }
//箭頭函式可以賦值給變數,也可以像匿名函式一樣直接作為引數傳遞
var sum = (num1,num2)=>{
return num2+num1;
}
console.log(sum(3,5));
var add = (num1,num2)=>num1+num2;
console.log(add(1,2))
//使用箭頭函式實現函式自執行
var person = (name=>{
return {
name:name,
age:30,
}
})('huzhenyu');
console.log(person);//使用箭頭函式返回一個物件,age預設,name是進行傳參
let page = {
id:'132323',
init:function () {
console.log('init',this);
// 在此處this的和init函式內的this相同。
document.addEventListener('click',
(event)=>{
this.doSomething(event.type)
console.log('event',this)
}
,false);
},
doSomething:function (type) {
console.log('handle'+type+'for'+this.id);
}
};
page.init();
//箭頭函式無this繫結
var p = {
foo:()=>console.log(this) //此處this為window
}
p.foo(); //輸出為 window物件。 並不是我想要的。所以在定義物件的方法的時候應該避免使用箭頭函式。
//箭頭函式一般用在傳遞引數,或者在函式內部宣告函式的時候使用。