【javascript】高阶函数的应用

news/2024/7/5 20:45:00 标签: javascript

文章目录

      • 1、什么是高阶函数:
      • 2、高阶函数的应用:
        • 1. AOP 面向切片编程
        • 2. vue 2.0 也会用到 函数劫持(AOP切片)的思想
        • 3. react 里的setState的事务transcation
        • 4. 保存变量

说到异步肯定要说到回调函数:回调函数是高阶函数的一种;

1、什么是高阶函数:

  • 如果函数的参数是一个函数
javascript">function (func){
	func();
}
  • 一个函数返回了一个函数(返回函数)
javascript">function (){
	return function (){}
}

2、高阶函数的应用:

1. AOP 面向切片编程

或者重写一些方法的时候会用到

javascript">function say() {
	//todo...
	console.log('hello')
}
//拓展函数,不想破环原有的函数,不然别人调用say(),say就被修改了。但还想在函数之前或之后添加一些逻辑

// 这是我们设想的最后实现的方法befor的使用方式

Function.prototype.befor = function (func) {
	//给befor方法一个参数,这个参数就是要执行的逻辑参数
	let that = this;   //最后say 调用befor方法,所以这里this指向say方法。
	// 但是在下面的返回函数里,this指向调用这个函数的对象,在浏览器里是window,不是say,所以这里我们把this的指向存在变量that里
	//这是闭包的私有变量,因为被返回函数使用,所以不会被销毁
	return function () {
		func();       //在返回的参数里,先执行要添加的逻辑
		that();      //然后执行say方法里的逻辑
	}
}

let newSay = say.befor(function () {
	//让say方法,调用一个方法befor,然后把想要添加的逻辑作为参数传进去,这个方法执行完返回一个函数,这个函数是两个函数的拼接
	console.log('我先执行再say');
})
newSay();

// 我们按照上面的使用方法进行编写
// 我们希望所有的函数都有befor方法,都可以在执行之前先执行别的函数,所以加在Function.prototype

上面这个方法里的this问题也可以用es6的箭头函数来写

javascript">Function.prototype.befor = function (func) {
	return () => {   //箭头函数没有this,没有arguments, 没有原型
		func();       
		this();      //因为没有this,所以向上查找,它的上一级函数里this 指向say方法
	}
}

我们也可以给say方法传参数

javascript">function say(who) { //1.这里有个参数:形参
	//todo...
	console.log(who + ' hello')
}

Function.prototype.befor = function (func) {
	// ...args 剩余运算符:将所有的参数组合成一个数组,只能在最后一个参数里使用
	return (...args) => {    //3.执行逻辑时,获取实参并进行处理, 这个返回的函数,就是最后赋值给newSay的函数
	//如果不是箭头函数,可以直接用arguments 来获取实参列表,但是箭头函数没有arguments	
	//当然如果知道有几个参数,也可以写死
		func();
		this(...args);      //展开运算符
	}
}

let newSay = say.befor(function () {
	console.log('我先执行再say');
})
newSay('lxz');  // 2.实参:say 没有单独调用执行,而是在这里调用执行的,所以实参应该写在这里 

什么叫闭包? 有一个函数,这个**函数可以不在当前作用域下执行,可以在外面执行,并且可以拿到之前作用域的值==**;
作用域什么时候产生的?作用域的产生是 根据函数定义的位置,函数执行的时候是执行上下文

2. vue 2.0 也会用到 函数劫持(AOP切片)的思想

函数劫持(AOP切片)的思想

javascript">
[1,2,3].push(4);   //我们希望 在调用push方法的时候,触发一句更新操作。相当于我们把push方法重写了
let oldPush = Array.prototype.push;  // 拿到老的push方法
// Array.prototype.push 放在原型上会好用些
function push(...args){   //我们自己写一个push方法,但是这样写我们调用方法就只能 push();  
	// 本来应该写形参a,但是不知道有多少个参数,所以可以把参数放到一个数组里,利用剩余运算符,转为数组 ...args
	//传的是4,5,6 ; 也就是...args 是4,5,6;那args是[4,5,6]
	// 不能用 xx.push()这样调用了,那push里的this不能用了,我们要用this可以用call /apply
	console.log('数据更新了')
	oldPush.call(this,...args);   //在这里调用原来的push, 这里是展开运算符
	// 但是 oldPush() 这样写,oldPush里的this并不是指向数组,还需要通过call来改变this指向
	//因为 oldPush 也就是 Array.prototype.push 里面的实现也用到了this,所以要用call改变this指向
}
let arr = [1,2,3];
push.call(arr,4,5,6)  //[1,2,3]第一个参数改变push里的this指向,后面的都是参数,我们用arguments 或者 ...args 剩余运算符获取
// call的特点:1.改变this指向  1.可以让push方法执行
// 4,5,6 是实参,有实参就要在定义的地方写下形参 -1实参
console.log(arr);

3. react 里的setState的事务transcation

如下图,给任何一个方法加上多层 init初始化的方法 和 close关闭的方法,实现猜想:
在这里插入图片描述

javascript">// react 里的setState就用到了事务的概念
function perform(anyMethod, wrappers) {  //参数传一个函数,任何的方法
    return function(){  //如果不想代码直接执行,就放在一个函数里返回,想执行的时候调用,这又是一个闭包
        wrappers.forEach(wrapper => wrapper.initialize())   //这是添加的bofor功能
        //forEach 的第一项是数组里的每一个元素,wrapper就是个名字,
        //这里是循环完wrappers,每项都执行一次initialize()
        // 箭头函数只有一个参数,可以省略(),没有return 可以省略{}
        anyMethod();  //这是核心功能
        wrappers.forEach(wrapper => wrapper.close());  //这是添加的after 功能
    }
}
//perform 就是一个高阶函数

let newFunc = perform(function () {   //perform,参数时一个函数,返回一个函数; 所以时高阶函数
    console.log('这里是say方法');

}, [  //perform的第二个参数是一个数组,里面每一项都是一个对象,对象里是一层添加的方法
    {  //wrapper1
        initialize() {
            console.log('beforSay1');
        },
        close() {
            console.log('close1');
        }
    }, { //wrapper2
        initialize() {
            console.log('beforSay2');
        },
        close() {
            console.log('close2');
        }
    }
]);
newFunc();

4. 保存变量

如下:要函数执行3次后,才调用回调函数,必须把3次这个times 利用闭包,保证其不会被销毁,不然每次调用完被销毁了,那下次调用还是从3开始算;
下面这个函数,只有第3次执行,超过了也不执行

javascript">function after(times, callback) {  //这是一个闭包,它的参数在返回的函数中有用到,它的执行期上下文AO对象永远不会被销毁
	//AO{times:3;} 
    //高阶函数的应用:times 永远被保存在作用域里;
    return function () {    //newFunc ,并且它不在这里执行,这定义它的作用域的外面执行,且能拿到外面的变量
        if (--times === 0) {   //--times  就是times -= 1   就是 times = times -1 
            // 这里先计算times = times-1 然后将减后的times 和 0 做比较
            callback();
        }
    }
}

let newFunc = after(3, function () {    //after的第一个参数是这个函数调用3次后,才会执行后面的回调函数
    //after的参数传要真正执行的函数
    console.log('真正执行的函数');

})
newFunc();
newFunc();
newFunc();  

http://www.niftyadmin.cn/n/1147738.html

相关文章

2008大连春季房交会落幕 成交量比去年降低

2008大连春季房交会于昨天正式落下帷幕,记者昨天从组委会获悉,本届房交会期间,共有19万人次参观展会,四天共成交商品房1084套,成交二手房226套,商品房成交量比去年春季、秋季两届房交会的1126套和1104套成交…

前端_JavaScript_Vue

Tips(1)项目仪表盘在Vue-cli中,内置项目仪表盘 在本地文件中$vue ui打开(2)创建项目$yarn global add vue/cli $ vue ui vue-router 在SPA中,路由是组件之间的切换,路由模块的本质是建立组件与页面之间的映射关系.SPA的路由是只更新视图而不重新请求页面.根据mode参数不同可以选…

【javascript】高阶函数2 - 异步编程 初

文章目录目标方案1:串行 -不推荐方案2:通过回调函数来解决-很麻烦方案3:after函数的方式 - 相对好一些方案4:发布订阅模式(发布 和 订阅)引申:观察者模式let fs require(fs); //引入fs api &…

22届大连国际马拉松赛周日鸣枪 五大特点备受瞩目

以“相聚大连,共迎奥运”为主题的第22届“全日空”杯大连国际马拉松赛,将于4月20日(本周日)7时30分在星海广场百年城雕广场鸣枪开赛。记者从昨日下午召开的赛会新闻发布会上获悉,共有来自世界五大洲36个国家和地区、国…

沙漏

题目1:本题要求你写个程序把给定的符号打印成沙漏的形状。例如给定17个“*”,要求按下列格式打印 ************ *****所谓“沙漏形状”,是指每行输出奇数个符号;各行符号中心对齐;相邻两行符号数差2;符号数…

俄罗斯计划派猴子前往火星 为宇航员探路

中新网4月15日电 据英国广播公司14日报道,俄罗斯计划派猴子前往火星以便为人类宇航员探路。它们将是首批经受辐射的动物,辐射对飞往火星的宇航员构成了很大的风险。 俄罗斯索契的灵长类动物医学研究所曾多次参加前苏联和俄罗斯的太空项目。研究所所长波…

【Promise】1-简单用法 及 原理

文章目录1.promise 简单用法2.Promise 实现原理3. promise里then的‘发布订阅’4. promise里then的用法promise 有哪些优缺点?优点: 1.可以解决异步嵌套的问题; 2.可以解决多个异步并发问题 缺点 1.promise 基于回调的(要不停的写函数) 2.pro…

PCB板HDI板几阶是什么意思

http://blog.sina.com.cn/s/blog_55ff6d5d0102xxvx.html转载于:https://www.cnblogs.com/duwenqidu/p/10392957.html