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对象。 并不是我想要的。所以在定义对象的方法的时候应该避免使用箭头函数。
//箭头函数一般用在传递参数,或者在函数内部声明函数的时候使用。