本人已参与「新人创作礼」活动,一起开启掘金创作之路。
前言
大家好,我是掘金新用户小钻风头领,今天是我正式更文的第四天;
五、函数优化
5.1、参数展开/rest参数/剩余参数/可变参数
剩余参数是将剩下的参数收集起来放在一个数组中。
5.1.1、案例1:rest参数
<script type="text/javascript">
// 函数展开/可变参数
function info(num1,num2,...args){
alert(num1);
alert(num2);
alert(args); // 30,40,50,args是一个数组,以数组的方式接收函数中剩余的参数
}
info(10,20,30,40,50);
</script>
==作用:收集函数参数中剩余的参数,必须作为最后一个参数位置。==
5.1.2、案例2:展开数组
<script type="text/javascript">
let arr1 = [1,2,3];
let arr2 = [4,5,6];
let arr3 = [...arr1 , ...arr2];
alert(arr3);
</script>
5.2、函数参数默认值
5.2.1、之前如何实现
在ES6之前是不提供函数默认参数值的实现,只能通过变通写法。
<script type="text/javascript">
// 假设num2的默认值是2
function add(num1, num2){
if (!num2){
num2 = 2;
}
return num1 + num2;
}
console.info(add(10)); // 12
console.info(add(10 , 8)); // 18
</script>
5.2.2、案例
<script type="text/javascript">
// 假设num2的默认值是2
function add(num1, num2 = 2){ // 直接在参数上直接赋值即可
return num1 + num2;
}
console.info(add(20)); // 22
console.info(add(20 , 8)); // 28
</script>
5.3、箭头函数
5.3.1、之前定义函数
<script type="text/javascript">
// 使用function关键字定义函数.
function show(username){
console.info("Hello:" + username);
}
show("张三");
</script>
5.3.2、案例1:单个参数
<script type="text/javascript">
let show = username => console.info("Hello:" + username);
show("李四");
</script>
/**
语法:
let 函数名 = 参数名 => 函数体
*/
5.3.3、案例2:多个参数
<script type="text/javascript">
let add = (num1,num2) => console.info(num1 + num2);
add(10,20);
</script>
/*
多个参数需要使用【()】小括号给括起来.
*/
5.3.4、案例3:没有参数
<script type="text/javascript">
let info = () => console.info("打印信息");
info();
</script>
/*
即使函数没有参数,也需要使用【()】小括号来去表示,来去代表参数部分
*/
5.3.5、案例4:函数体有多条语句
<script type="text/javascript">
let length = (str) => {
if(str){
return str.length;
}
return 0;
}
console.info(length("123"));
</script>
/*
函数体有多条语句时候,需要使用【{}】花括号包裹起来
*/
5.3.6、案例5:关于函数体的其他说明
如果函数中有单个表达式或语句:那么==1、函数体外部的{}是可以省略的;2、使用return可以省略。==
5.3.6.1、细节1:如果是单个表达式,则自带return
<script type="text/javascript">
// 求两个数的和
let sum = (num1 , num2) => {
return num1 + num2;
}
alert(sum(10,30));
</script>
<script type="text/javascript">
// 求两个数的和
let sum = (num1 , num2) => num1 + num2; // 自带return
alert(sum(10,30));
</script>
5.3.6.2、细节2:如果是单条语句,花括号可以省略
<script type="text/javascript">
// 求两个数的和
let sum = (num1 , num2) => {
alert(num1 + num2);
}
sum(10,25);
</script>
<script type="text/javascript">
// 求两个数的和
let sum = (num1 , num2) => alert(num1 + num2);
sum(10,25);
</script>
5.3.7、箭头函数中的this
在普通函数中的this指向的是谁调用了这个函数,那么这个函数中的this就是谁。
==箭头函数不绑定this,换句话说,箭头函数是没有自己的this,如果在箭头函数中使用this,那么this指向的是箭头函数所在定义位置中的this,也就是说箭头函数定义在哪里,箭头函数中的this就指向谁。通俗一点说,箭头函数里的this指的是定义这个箭头函数时外层代码的this。==
5.3.7.1、案例1
-
ES5代码
<script type="text/javascript"> function Person(){ this.username = "HelloWorld"; this.run = function(){ console.info(this.username + "在跑步"); } } var p1 = new Person(); // HelloWorld在跑步,原因是run方法是p1对象调用者,那么run方法中的this指向的就是p1这个实例对象,而p1的实例对象中有username属性是HelloWorld. p1.run(); var p2 = p1.run; // undefined在跑步 , 原因是run方法是window对象直接调用的,那么run方法中的this指向的就是window,而window是没有username属性的,所以是undefined。 p2(); </script> -
ES6代码
<script type="text/javascript"> function Person(){ this.username = "HelloWorld"; this.run = () => { console.info(this.username + "在跑步"); } } var p1 = new Person(); // HelloWorld在跑步 p1.run(); var p2 = p1.run; // HelloWorld在跑步,可以看到,更改了run方法的调用,但是依然没有影响到run方法中的this的指向 p2(); </script><script type="text/javascript"> function Person(){ this.username = "HelloWorld"; this.run = () => { console.info(this.username + "在跑步"); } } // 先调用一下 Person(); var p2 = run; // HelloWorld在跑步 p2(); </script>==可以发现:箭头函数中的this的指向就是:箭头函数定义在哪里,那么箭头函数中的this指向就是哪里,箭头函数中的this就是外层代码this的引用。本例:箭头函数中的this就是Person函数中的this。==
5.3.7.2、案例2
-
ES5代码
<script type="text/javascript"> var person = {username: "HelloWorld"}; function fn1(){ return function(){ console.info(this.username); } } var fn = fn1.call(person); fn(); // undefined </script> -
ES6代码
<script type="text/javascript"> var person = {username: "HelloWorld"}; function fn1(){ return ()=> { console.info(this.username); } } var fn = fn1.call(person); fn(); // HelloWorld </script>
5.3.7.3、案例3
-
ES5代码
<script type="text/javascript"> var obj = { age: 20, run: function(){ console.info(this.age); } }; obj.run(); // 20 </script> -
ES6代码
<script type="text/javascript"> var obj = { age: 20, run: ()=>{ console.info(this.age); } }; obj.run(); // undefined </script>
5.4、对象的函数属性简写
5.4.1、之前写法
<script type="text/javascript">
let person = {
username : "张三",
run: function(address){ // 属性:function函数
console.info(this.username + "在" + address + "跑步");
}
};
person.run("操场");
</script>
5.4.2、箭头函数写法
<script type="text/javascript">
let person = {
username : "张三",
run: (address) => {
console.info(person.username + "在" + address + "跑步")// 注意这里不能用this.username
}
};
person.run("操场");
</script>
5.4.3、对象的函数属性写法
<script type="text/javascript">
let person = {
username : "张三",
run(address){ // 在对象中直接定义函数。
console.info(this.username + "在" + address + "跑步");
}
};
person.run("操场");
</script>
5.4.4、对象的其他简单写法
-
以前写法
<script type="text/javascript"> let name = "HelloWorld"; let age = 23; let person = {name:name , age:age}; console.info(person.name + "," + person.age); </script> -
ES6新写法
键值对出现了重复,ES6 中,如果属性名和和所分配的变量名一样,就可以从对象属性中删掉这些重复的变量名称。
<script type="text/javascript"> let name = "HelloWorld"; let age = 23; let person = {name, age}; console.info(person.name + "," + person.age); </script>
5.5、箭头函数结合解构表达式
5.5.1、之前写法
<script type="text/javascript">
let person = {
username: "张三",
age: 12
}
// 打印对象
function info(obj){
console.info("姓名是:" + obj.username);
}
info(person);
</script>
5.5.2、改进1:使用箭头函数
<script type="text/javascript">
let person = {
username: "李四",
age: 12
}
let info = (obj) => console.info("姓名是:" + obj.username);
info(person);
</script>
5.5.3、改进2:使用箭头函数+解构表达式
<script type="text/javascript">
let person = {
username: "王五",
age: 12
}
let info = ({username:name}) => console.info("姓名是:" + name);
info(person);
</script>
5.6、map和reduce
5.6.1、map:映射
5.6.1.1、说明
map():该函数的参数接收一个函数fn,将原数组中的所有元素用这个fn函数处理后放入新数组返回。
5.6.1.2、案例1
==给定一个数组,将数组中的每个元素求平方然后组成一个新的数组==
<script type="text/javascript">
let arrs = [1,2,3,4,5,6];
let arrsNew = arrs.map(item => {
return item * item;
});
console.info(arrsNew);
</script>
<script type="text/javascript">
let arrs = [1,2,3,4,5,6];
let arrsNew = arrs.map(item => item * item); // 使用箭头函数改造一下
console.info(arrsNew);
</script>
5.6.2、reduce:合并/汇总
5.6.2.1、说明
reduce() :该函数的参数接收一个函数fn(必须)和一个初始值value(可选),fn函数接收两个参数:
-
第一个参数是上一次reduce处理的结果
-
第二个参数是数组中要处理的下一个元素
reduce()会从左到右依次把数组中的元素用reduce处理,并把处理的结果作为下次reduce的第一个参数。如果是第一次,会把前两个元素作为计算参数,或者把用户指定的初始值作为起始参数。
5.6.2.2、案例1:没有初始值
==给定一个数组,求数组中所有元素的和==
<script type="text/javascript">
let arrs = [1,2,3,4,5,6];
let result = arrs.reduce((a,b) => {
return a + b;
});
console.info(result); // 21
</script>
5.6.2.3、案例2:有初始值
==给定一个数组,求数组中所有元素的和,指定一个初始值10==
<script type="text/javascript">
let arrs = [1,2,3,4,5,6];
let result = arrs.reduce((a,b) => {
return a + b;
},10);
console.info(result);
</script>
5.7、filter:过滤
5.7.1、说明
用于把数组中的某些元素过滤掉,返回剩下的符合条件的元素。实现方式是:filter函数的参数接收一个函数,然后把传入的函数作用于每一个元素,然后根据返回值是true和false决定保留还是丢掉该元素。
5.7.2、案例
给定一个数组,过滤掉不能被3整除的数,然后返回新数组。
<script type="text/javascript">
// 过滤掉不能被3整除的数
let arrs = [12,34,56,41,24];
let result = arrs.filter(function(item){
return item % 3 == 0;
});
console.info(result);
</script>
<script type="text/javascript">
// 过滤掉不能被3整除的数
let arrs = [12,34,56,41,24];
let result = arrs.filter(item => item % 3 == 0); // 使用箭头函数实现
console.info(result);
</script>
5.8、forEach:迭代
5.8.1、说明
用来遍历数组
5.8.2、案例
<script type="text/javascript">
// 过滤掉不能被3整除的数
let arrs = [12,34,56,41,24];
arrs.forEach(function(item,index){
alert(index + ", " + item);
})
</script>
<script type="text/javascript">
// 过滤掉不能被3整除的数
let arrs = [12,34,56,41,24];
arrs.forEach((item,index) => {alert(index + ":" + item)});
</script>