1、普通函数
function showName(name){
alert(name)
}
1)JS中同名函数的覆盖
在js中函数是没有重载的,定义相同的函数名,不同参数签名的函数,后面的函数会覆盖前面的函数。调用时,只会调用后面的函数
ss(){
let o={0:45,1:56,2:89,length:3};
for(let i=0;i<o.length;i++){ //length
console.log('第'+i+'个数为:'+o[i]);
}
},
ss(){
let o={0:45,1:56,2:89,length:3};
for(let i=0;i<o.length-1;i++){ //length-1
console.log('第'+i+'个数为:'+o[i]);
}
}
这两个函数定义在一起是,执行第二个函数,第一个函数被覆盖
类数组对象:
ss(){
let o={0:45,1:56,2:89,length:3}; //类数组对象
for(let i=0;i<o.length;i++){
console.log('第'+i+'个数为:'+o[i]);
}
}
函数的调用方法:
1.test()
2.test.call(this,参数列表)
3.test.apply(this,参数数组)
2、匿名函数
变量匿名函数
可以把函数赋值给变量,事件
mounted(){
let some=function(a,b){
return a*b;
}
console.log( 'a*b='+ some(3,4)); //a*b=12
}
优点:避免函数名污染。若先声明个带名称的函数,再赋值给变量或事件,就造成了函数名的滥用
无名称匿名函数
在函数声明时,在后面紧跟参数,js解析此函数时,里面的代码立即执行
(function(){ //数据
var dataList=[];
var text=['直接','邮件','联盟','搜索','视频']
for(var i=0;i < text.length ;i++){
dataList.push({"value": Math.floor(Math.random()*2000),'name':text[i]})
}
return dataList;
})(),
该函数只需执行一次,如浏览器加载完,只需要执行一次且后面不执行该功能
3、闭包函数
闭包特点:
1)函数嵌套函数
2)函数内部可引用函数外部的变量
3)参数和变量不会被垃圾回收机制回收(一般情况下,函数执行完之后,连同里面的变量一起被销毁,但闭包中的变量要主动销毁)
优点:
1)保护函数内的变量安全,实现封装,防止变量流入其他环境发生命名冲突
2)在内存中维持一个变量,可做缓存(但消耗内存)
3)匿名自执行函数可减少内存消耗
缺点:
1)被引用的私有变量不能被销毁,增大内存消耗,造成内存泄漏。解决:使用完后手动为它赋值为null
2)闭包涉及跨域访问,故导致性能损失,可通过把跨域作用域存储在局部变量中,然后直接访问局部变量,减轻对执行速度的影响
函数作为返回值
function fn(){
let num=3;
return function(){ //函数作为参数
let n=0;
console.log(++n);
console.log(++num);
}
}
let fn1=fn();
fn1(); //1 4
fn1(); //1 5
匿名函数内部引用fn中变量num,形成闭包,变量num无法被销毁,而n是每次调用时被创建
fn1执行完后就把属于自己的变量连同自己一起销毁,最后剩下num,产生内存消耗问题
aa(){
for(var i=0;i<5;i++){ //var
setTimeout(function(){
console.log(i+' '); // 5 5 5 5 5
},100)
}
}
js是单线程,for循环时,setTimeout在任务队列中等待,在等待时for循环执行完,setTimeout执行完时,for循环结束,i的值为5,故打印出5个5
function bb(){
for(let i=0;i<5;i++){ //let
setTimeout(function(){
console.log(i+' '); //1 2 3 4 5
},100)
}
}
函数作为参数传递
var num=15;
var fn1=function(x){
if(x>num){
console.log(x)
}
}
void function(fn2){ //立即执行函数
var num=100;
fn2(30);
}(fn1);
把fn1作为参数传入立即执行函数中,执行到fn2(30)时,30作为参数传入fn1中,此时,x=30,num为函数作用域中的num=15,即30>15,打印出30