高阶函数
高阶函数是什么?
定义:高阶函数是对其他函数进行操作的函数,它接收函数作为参数或者将函数作为返回值输出。
接收函数传给回调函数
例如:jquery
<script>
function fn(a,b,callback){
console.log(a+b);
//回调函数
//函数传给collback
callback&&callback();
}
fn(1,2,function(){
console.log('我是最后调用的');
});
</script>
返回的是函数类型
<script>
function fn(){
return function(){}
}
fn();
</script>
原理是什么?
因为JavaScript中函数可以作为参数,同样可以作为返回值,可以传递给回调函数。
闭包(closure)
闭包的定义
定义:闭包指有权访问另一个函数作用域中变量的函数。
简单地说:一个作用域可以访问另一个函数内部局部变量。
闭包:我们fun这个函数作用域访问了另外一个函数fn作用域的局部变量num
闭包函数:被访问的函数称为闭包函数
<script>
//闭包:我们fun这个函数作用域访问了另外一个函数fn作用域的局部变量num
function fn(){
var num=10;
function fun(){
console.log(num);
}
fun();
}
fn();
</script>
调用过程?
- fn函数调用
- 到了num,此时没有值,为undefine
- 到了fun(),调用fun函数。
- 执行fun(){}函数,到了fun函数,此时有了闭包closure(fn)
- 访问fn的局部变量num
闭包的作用?
- fn外部作用域可以访问fun内部局部变量。函数外部作用域或者全局作用域可以访问局部变量。
- **延伸了变量的作用范围。**局部变量执行完后不会立刻销毁。
<script>
//fn外面的作用域可以访问fn内部局部变量
function fn(){
var num=10;
function fun(){
console.log(num);
}
return fun;
}
var f=fn();
//f存的是fun
f();
//类似于
var f=function(){
console.log(num);
}
==================================
//fn外面的作用域可以访问fn内部局部变量
function fn(){
var num=10;
return function(){
console.log(num);
}
}
//f存的是function
var f=fn();
f();
</script>
闭包案列
- 闭包模板:将模板里的函数从异步改为同步的(函数跟for循环同步,立刻执行。
- function()最外层函数称作闭包函数。
- 作用:增大变量范围。
(function(i){
//函数
})(i);
点击某一个li输出对应li的索引号
- for循环同步任务,马上执行。onlick异步任务,不会立刻执行。
- 闭包是立即执行函数
普通方式
<body>
<ul class="nav">
<li>榴莲</li>
<li>臭豆腐</li>
<li>鲱鱼罐头</li>
<li>大猪蹄子</li>
</ul>
<script>
//动态添加属性
var lis=document.querySelector('.nav').querySelectorAll('li');
for(var i=0;i<lis.length;i++){
//index为0 1 2 3
lis[i].index=i;
lis[i].onclick=function(){
console.log(this.index);
}
}
</script>
</body>
闭包方式
- 第1个i传递给第5个i
- 第5个i传递给第2个i
- 点击第i个小li时。(lis[i].onclick)
- 打印出第4个i。
<body>
<ul class="nav">
<li>榴莲</li>
<li>臭豆腐</li>
<li>鲱鱼罐头</li>
<li>大猪蹄子</li>
</ul>
<script>
//动态添加属性
var lis=document.querySelector('.nav').querySelectorAll('li');
//闭包
//第1个i传递给第5个i,第5个i传递给第2个i,点击第i个小li时。打印出第4个i。
for(var i=0;i<lis.length;i++){
//利用for循环创建4个立即执行函数
//立即执行函数又叫小闭包,因为立即函数里面任何一个函数都可以使用它的i变量。
//()();
(function(i){
//console.log(i);
lis[i].onclick=function(){
//闭包,用了第一个function中二个i的值。
console.log(i);
}
})(i);
}
</script>
立即执行函数又叫小闭包,因为立即函数里面任何一个函数都可以使用它的i变量。
闭包体现:用了第一个function中function(i)中i的值。
总结:for循环马上结束,而函数效果会一直保存。
当鼠标点击li时,调用lis[i].οnclick=function()。输出函数内的值。
三秒后,控制台打印li中所有元素
定时器里的回调函数都是异步任务。只是触发了才执行,即3秒后才执行。就算改成0也不会立刻执行,会把任务放到异步队列中。而for循环同步任务,马上执行。
<script>
//动态添加属性
var lis=document.querySelector('.nav').querySelectorAll('li');
for(var i=0;i<lis.length;i++){
(function(i){
setTimeout(function(){
console.log(lis[i].innerHTML);
},3000)
})(i);
}
</script>
输入公里数,输出打车价格
起步价13(3公里内) 每一公里加3 元
有拥堵,加10块度车费。
<script>
var car=(function(){
var start=13;
var total=0;
return {
price: function(n){
if(n<=3){
return start;
}
else{
total=start+(n-3)*5;
return total;
}
},
yd:function(flag){
if(flag=true)
return total+10;
else return total;
}
}
})();
console.log(car.price(5));//23
console.log(car.yd(true));//33
console.log(car.yd(false));//33
console.log(car.price(1));//覆盖n=5 total=13
</script>
- 闭包:外面function访问里面function的total和start
- 注意:局部变量会被新的值覆盖。