Dieser Artikel bietet Ihnen eine Einführung in Funktionen höherer Ordnung in JavaScript (Codebeispiele), auf die sich Freunde in Not beziehen können Ich hoffe, dass es Ihnen hilfreich sein wird.
Eine Funktion kann eine andere Funktion als Parameter empfangen. Kurz gesagt, die Parameter der Funktion können andere Funktionen empfangen.
JavaScript-Funktionen höherer Ordnung sind ähnlich zu Swifts Funktionen höherer Ordnung
Übliche Funktionen höherer Ordnung umfassen: Zuordnen, Reduzieren, Filtern, Sortieren
Funktionen höherer Ordnung beziehen sich auf Funktionen, die mindestens eine der folgenden Bedingungen erfüllen Bedingungen
1: Funktionen können als Parameter übergeben werden
2: Funktionen können als Rückgabewerte ausgegeben werden
Funktionen in der JavaScript-Sprache erfüllen offensichtlich höhere- Ordnungsfunktionen Bedingungen, lassen Sie uns den Charme der Funktionen höherer Ordnung von JavaScript erkunden.
Funktionen höherer Ordnung implementieren AOP
Die Hauptfunktion von AOP (aspektorientierte Programmierung) besteht darin, einige Funktionen zu extrahieren, die nichts mit der Kerngeschäftslogik zu tun haben Modul und verwenden Sie dann die Methode „Dynamisches Weben“, die in Geschäftsmodule integriert ist. Zu diesen Funktionen gehören im Allgemeinen Protokollstatistiken, Sicherheitskontrolle, Ausnahmebehandlung usw. AOP ist der Kern der Java Spring-Architektur. Lassen Sie uns untersuchen, wie man AOP in JavaScript implementiert.
Die Implementierung von AOP in JavaScript bezieht sich auf das „dynamische Einbinden“ einer Funktion in eine andere Funktion. Dazu verwenden wir Function.prototype. Der Code lautet wie folgt:
/** * 织入执行前函数 * @param {*} fn */ Function.prototype.aopBefore = function(fn){ console.log(this) // 第一步:保存原函数的引用 const _this = this // 第四步:返回包括原函数和新函数的“代理”函数 return function() { // 第二步:执行新函数,修正this fn.apply(this, arguments) // 第三步 执行原函数 return _this.apply(this, arguments) } } /** * 织入执行后函数 * @param {*} fn */ Function.prototype.aopAfter = function (fn) { const _this = this return function () { let current = _this.apply(this,arguments)// 先保存原函数 fn.apply(this, arguments) // 先执行新函数 return current } } /** * 使用函数 */ let aopFunc = function() { console.log('aop') } // 注册切面 aopFunc = aopFunc.aopBefore(() => { console.log('aop before') }).aopAfter(() => { console.log('aop after') }) // 真正调用 aopFunc()
Currying (Currying)
Das erste, worüber wir über Curring sprechen müssen, ist, was Funktions-Currying ist.
Curring wird auch Teilauswertung genannt. Eine aktuelle Funktion akzeptiert zunächst einige Parameter. Nach der Annahme dieser Parameter wertet die Funktion nicht sofort aus, sondern gibt weiterhin eine andere Funktion zurück. Die gerade übergebenen Parameter werden im von der Funktion gebildeten Abschluss gespeichert. Wenn die Funktion tatsächlich ausgewertet werden muss, werden alle zuvor übergebenen Parameter auf einmal zur Auswertung verwendet.
Es ist nicht einfach, das Konzept auf eine starre Art und Weise zu verstehen. Schauen wir uns das nächste Beispiel an.
Wir benötigen eine Funktion, um den Verbrauch für 12 Monate in einem Jahr zu berechnen, und wir müssen ihn zum Zeitpunkt der Berechnung berechnen Ende jedes Monats Wie viel Geld wurde verbraucht. Der normale Code lautet wie folgt:
// 未柯里化的函数计算开销 let totalCost = 0 const cost = function(amount, mounth = '') { console.log(`第${mounth}月的花销是${amount}`) totalCost += amount console.log(`当前总共消费:${totalCost}`) } cost(1000, 1) // 第1个月的花销 cost(2000, 2) // 第2个月的花销 // ... cost(3000, 12) // 第12个月的花销
Zusammenfassend ist es nicht schwer herauszufinden, dass wir den Gesamtverbrauch eines Jahres nicht 12 Mal berechnen müssen, wenn wir ihn berechnen möchten. Wir müssen nur eine Berechnung am Ende des Jahres durchführen, um das Verständnis dieser Funktion zu erleichtern. Als nächstes schreiben wir eine allgemeine Berechnung und eine Funktion, die berücksichtigt wird. Der Code lautet wie folgt:
// 部分柯里化完的函数 const curringPartCost = (function() { // 参数列表 let args = [] return function (){ /** * 区分计算求值的情况 * 有参数的情况下进行暂存 * 无参数的情况下进行计算 */ if (arguments.length === 0) { let totalCost = 0 args.forEach(item => { totalCost += item[0] }) console.log(`共消费:${totalCost}`) return totalCost } else { // argumens并不是数组,是一个类数组对象 let currentArgs = Array.from(arguments) args.push(currentArgs) console.log(`暂存${arguments[1] ? arguments[1] : '' }月,金额${arguments[0]}`) } } })() curringPartCost(1000,1) curringPartCost(100,2) curringPartCost()
Funktionsdrosselung
Die meisten Funktionen in JavaScript werden aktiv vom Benutzer ausgelöst. Im Allgemeinen gibt es kein Leistungsproblem, aber in einigen Sonderfällen werden sie nicht direkt vom Benutzer gesteuert. Bei einer großen Anzahl von Aufrufen kann es leicht zu Leistungsproblemen kommen. Schließlich sind DOM-Operationen sehr teuer. Einige solcher Szenarien sind unten aufgeführt:// 通用curring函数 const curring = function(fn) { let args = [] return function () { if (arguments.length === 0) { console.log('curring完毕进行计算总值') return fn.apply(this, args) } else { let currentArgs = Array.from(arguments)[0] console.log(`暂存${arguments[1] ? arguments[1] : '' }月,金额${arguments[0]}`) args.push(currentArgs) // 返回正被执行的 Function 对象,也就是所指定的 Function 对象的正文,这有利于匿名函数的递归或者保证函数的封装性 return arguments.callee } } } // 求值函数 let costCurring = (function() { let totalCost = 0 return function () { for (let i = 0; i < arguments.length; i++) { totalCost += arguments[i] } console.log(`共消费:${totalCost}`) return totalCost } })() // 执行curring化 costCurring = curring(costCurring) costCurring(2000, 1) costCurring(2000, 2) costCurring(9000, 12) costCurring()
Die Drosselungsfunktion bietet uns eine Lösung, um die Häufigkeit von Funktionsaufrufen zu begrenzen. Als nächstes werden wir auf ein anderes Problem stoßen, aber aus bestimmten objektiven Gründen werden diese Vorgänge die Seitenleistung erheblich beeinträchtigen. Zu diesem Zeitpunkt müssen wir eine andere Methode verwenden, um es zu lösen.
Wenn wir in kurzer Zeit eine große Anzahl von DOM-Knoten in die Seite einfügen müssen, ist dies für den Browser offensichtlich überwältigend. Dies kann dazu führen, dass der Browser einfriert. Daher müssen wir Time-Sharing-Funktionen ausführen und stapelweise einfügen.
/** * 节流函数 * @param {*} fn * @param {*} interval */ const throttle = function (fn, interval = 500) { let timer = null, // 计时器 isFirst = true // 是否是第一次调用 return function () { let args = arguments, _me = this // 首次调用直接放行 if (isFirst) { fn.apply(_me, args) return isFirst = false } // 存在计时器就拦截 if (timer) { return false } // 设置timer timer = setTimeout(function (){ console.log(timer) window.clearTimeout(timer) timer = null fn.apply(_me, args) }, interval) } } // 使用节流 window.onresize = throttle(function() { console.log('throttle') },600)
Bei der Webentwicklung ist aufgrund der Unterschiede in einigen Browsern immer etwas Schnüffelarbeit unvermeidlich.
Aufgrund der Unterschiede bei den Browsern müssen wir häufig verschiedene Kompatibilitätsprobleme lösen. Nehmen wir ein sehr einfaches und häufig verwendetes Beispiel: eine Ereignisbindungsfunktion, die universell in allen Browsern verwendet werden kann.
Eine übliche Art, es zu schreiben, ist so:/** * 分时函数 * @param {*创建节点需要的数据} list * @param {*创建节点逻辑函数} fn * @param {*每一批节点的数量} count */ const timeChunk = function(list, fn, count = 1){ let insertList = [], // 需要临时插入的数据 timer = null // 计时器 const start = function(){ // 对执行函数逐个进行调用 for (let i = 0; i < Math.min(count, list.length); i++) { insertList = list.shift() fn(insertList) } } return function(){ timer = setInterval(() => { if (list.length === 0) { return window.clearInterval(timer) } start() },200) } } // 分时函数测试 const arr = [] for (let i = 0; i < 94; i++) { arr.push(i) } const renderList = timeChunk(arr, function(data){ let p =document.createElement('p') p.innerHTML = data + 1 document.body.appendChild(p) }, 20) renderList()
// 常用的事件兼容 const addEvent = function(el, type, handler) { if (window.addEventListener) { return el.addEventListener(type, handler, false) } // for IE if (window.attachEvent) { return el.attachEvent(`on${type}`, handler) } } 这个函数存在一个缺点,它每次执行的时候都会去执行if条件分支。虽然开销不大,但是这明显是多余的,下面我们优化一下, 提前一下嗅探的过程: const addEventOptimization = (function() { if (window.addEventListener) { return (el, type, handler) => { el.addEventListener(type, handler, false) } } // for IE if (window.attachEvent) { return (el, type, handler) => { el.attachEvent(`on${type}`, handler) } } })()
Sobald wir den Zweig betreten, wird die Implementierung der Funktion innerhalb der Funktion geändert. Nach dem Umschreiben ist die Funktion die Funktion, die wir erwarten, und wird beim nächsten Mal nicht mehr existieren Mal geben wir die bedingte Verzweigungsanweisung ein.
EndlichUm allen zu helfen, das Lernen einfacher und effizienter zu gestalten, werde ich eine große Menge an Informationen kostenlos mit Ihnen teilen, damit Sie ein vollwertiger Schornsteiningenieur oder sogar Architekt Es gibt viele Hindernisse auf dem Weg. Hier empfehle ich einen Front-End-Full-Stack-Lern- und Austauschkreis für alle:
866109386 Jeder ist herzlich willkommen, sich der Gruppe anzuschließen, um gemeinsam zu diskutieren, zu lernen und Fortschritte zu machen. Wenn Sie wirklich mit dem Lernen beginnen, wissen Sie unweigerlich nicht, wo Sie anfangen sollen, was zu einer geringen Effizienz führt und Ihr Selbstvertrauen in das weitere Lernen beeinträchtigt. Aber das Wichtigste ist, dass Sie nicht wissen, welche Technologien beherrscht werden müssen, und beim Lernen häufig auf Fallstricke stoßen, was letztendlich viel Zeit verschwendet, daher ist es immer noch notwendig, effektiv zu sein Ressourcen. Abschließend wünsche ich allen Front-End-Programmierern, die auf Engpässe stoßen und nicht wissen, was sie tun sollen, und alles Gute für Ihre zukünftige Arbeit und Ihre Interviews.
Das obige ist der detaillierte Inhalt vonEinführung in Funktionen höherer Ordnung in JavaScript (Codebeispiele). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!