Bei Front-End-Interviews ist das manuelle Zerlegen des Codes offensichtlich unvermeidlich und macht einen großen Teil davon aus. Programmierfragen werden hauptsächlich in folgende Typen unterteilt:
Den größten Anteil machen dabei die ersten beiden Typen aus. Dieser Artikel befasst sich hauptsächlich mit verschiedenen fokussierten Handschriften des zweiten Typs. Empfohlene Prioritäten:
1. Handschriftliche Instanz vonInstanceof-Funktion: Bestimmt, ob eine Instanz eine Instanz ihres übergeordneten oder Vorgängertyps ist. Während des Suchvorgangs durchläuft instanceof die Prototypenkette der Variablen auf der linken Seite, bis es den Prototyp der Variablen auf der rechten Seite findet. Wenn die Suche fehlschlägt, wird false zurückgegeben. let myInstanceof = (Ziel,Ursprung) => { während(Ziel) { wenn (ziel.__proto__===origin.prototype) { returniere wahr } Ziel = Ziel.__proto__ } return false } sei a = [1,2,3] console.log(meineInstanzvon(a,Array)); // wahr console.log(meineInstanzvon(a,Objekt)); // wahr 2. Implementieren Sie die Map-Methode des Arrays Verwendung: Konstante a = [1, 2, 3, 4]; const b = array1.map(x => x * 2); console.log(b); // Array [2, 4, 6, 8] Schauen wir uns vor der Implementierung die Parameter der Map-Methode an. Native Implementierung: // Implementiere Array.prototype.myMap = function(fn, thisValue) { lass res = [] dieserWert = dieserWert||[] lass arr = dies für(lass i=0; i<arr.length; i++) { res.push(fn.call(thisValue, arr[i],i,arr)) // Die Parameter sind dieser Zeiger, aktuelles Array-Element, aktueller Index, aktuelles Array} Rückgabewert } // Verwenden von const a = [1,2,3]; const b = a.meineMap((a,index)=> { gib a+1 zurück; } ) console.log(b) // Gibt [2, 3, 4] aus 3. Reduce implementiert die Map-Methode des Arrays Verwenden Sie die integrierte Array.prototype.myMap = Funktion(fn,dieserWert){ var res = []; dieserWert = dieserWert||[]; dies.reduzieren(Funktion(vor,aktuell,index,arr){ Führt eine Antwort auf die Frage aus, ob der Wert korrekt ist. },[]); Rückgabewert; } var arr = [2,3,1,5]; arr.myMap(Funktion(Element,Index,arr){ Konsole.log(Element, Index, arr); }) 4. Handgeschriebene Array-Reduzierungsmethode Die Methode
Funktion reduzieren(arr, cb, Anfangswert){ var num = initValue == undefiniert? num = arr[0]: initValue; var i = initValue == undefiniert? 1: 0 für (i; i< arr.length; i++){ Zahl = cb(Zahl,arr[i],i) } Rückgabenummer } Funktion fn(Ergebnis, aktuellerWert, Index){ Ergebnis + aktueller Wert zurückgeben } var arr = [2,3,4,5] var b = reduzieren(arr, fn,10) var c = reduzieren(arr, fn) console.log(b) // 24 5. Array-AbflachungArray-Flattening dient zur Konvertierung eines mehrdimensionalen Arrays in ein eindimensionales Array 5. 1 Neue Methode flat(depth) von es6 sei a = [1,[2,3]]; Tatsächlich gibt es einen einfacheren Weg. Sie müssen die Dimension des Arrays nicht kennen und können das Zielarray direkt in ein eindimensionales Array konvertieren. Der Tiefenwert ist auf Unendlich eingestellt. sei a = [1,[2,3,[4,[5]]]]; 5.2 Verwenden von cancatFunktion flatten(arr) { var res = []; für (sei i = 0, Länge = arr.Länge; i < Länge; i++) { wenn (Array.isArray(arr[i])) { res = res.concat(flatten(arr[i])); //concat ändert das ursprüngliche Array nicht //res.push(...flatten(arr[i])); //oder verwende den Spread-Operator} else { res.push(arr[i]); } } Rückgabewert; } sei arr1 = [1, 2,[3,1],[2,3,4,[2,3,4]]] abflachen(arr1); //[1, 2, 3, 1, 2, 3, 4, 2, 3, 4] Ergänzung: Tiefflach angeben Addieren Sie bei jeder Rekursion einfach den aktuellen Funktion flach(arr, tief) { lass res = [] für(lass i in arr) { wenn(Array.isArray(arr[i])&&deep) { res = res.concat(flach(arr[i],tief-1)) } anders { res.push(arr[i]) } } Rückgabewert } Konsole.log(flach([12,[1,2,3],3,[2,4,[4,[3,4],2]]],1)); 6. Funktions-CurryingSie können sich im vorherigen Artikel Front-End-JavaScript gründlich mit dem Funktionscurrying vertraut machen und die gleiche Methode verwenden, die hier verwendet wird. Die Definition von Currying lautet: Akzeptieren Sie einen Teil der Parameter, geben Sie eine Funktion zurück, um die verbleibenden Parameter zu akzeptieren, und führen Sie die ursprüngliche Funktion aus, nachdem genügend Parameter empfangen wurden. Wenn die Curry-Funktion genügend Parameter erhält, führt sie die ursprüngliche Funktion aus. Wie kann man feststellen, wann genügend Parameter erreicht sind? Es gibt zwei Ansätze:
Durch die Kombination dieser beiden Punkte können wir eine einfache Curry-Funktion implementieren: /** * Curry die Funktion * @param fn die ursprüngliche Funktion, die curryed werden soll * @param len die Anzahl der benötigten Parameter, standardmäßig die Anzahl der formalen Parameter der ursprünglichen Funktion */ Funktion Curry (fn, Länge = fn. Länge) { returniere _curry.call(diese,fn,länge) } /** * Übertragungsfunktion * @param fn ursprüngliche Funktion, die ausgeführt werden soll * @param len benötigte Anzahl Parameter * @param args empfangene Parameterliste */ Funktion _curry(fn,Länge,...Argumente) { Rückgabefunktion (...params) { let _args = [...args,...params]; if(_args.length >= len){ gibt fn.apply(diese,_args) zurück; }anders{ returniere _curry.call(diese,fn,länge,..._args) } } } Lassen Sie uns dies überprüfen: lass _fn = curry(Funktion(a,b,c,d,e){ konsole.log(a,b,c,d,e) }); _fn(1,2,3,4,5); // drucken: 1,2,3,4,5 _fn(1)(2)(3,4,5); // drucken: 1,2,3,4,5 _fn(1,2)(3,4)(5); // drucken: 1,2,3,4,5 _fn(1)(2)(3)(4)(5); // drucken: 1,2,3,4,5 Unsere häufig verwendete Toolbibliothek Wenn wir beispielsweise einen Platzhalter übergeben, überspringen die in diesem Aufruf übergebenen Parameter den Platzhalter und der Platzhalter wird mit den Parametern des nächsten Aufrufs gefüllt, wie folgt: Schauen Sie sich das Beispiel der offiziellen Website an: Als nächstes überlegen wir, wie die Platzhalterfunktion implementiert wird. Für die Da die von uns selbst implementierte Curry-Funktion auf keinem Objekt gemountet ist, verwenden wir die Curry-Funktion als Standardplatzhalter. Der Zweck der Verwendung von Platzhaltern besteht darin, die Reihenfolge zu ändern, in der Parameter übergeben werden. Daher muss bei der Implementierung der Curry-Funktion jedes Mal aufgezeichnet werden, ob ein Platzhalter verwendet wird und welche Parameterposition durch den Platzhalter dargestellt wird. Direkt zum Code: /** * @param fn die Funktion, die curryiert werden soll* @param length die Anzahl der erforderlichen Parameter, standardmäßig die Anzahl der formalen Parameter der Funktion* @param holder Platzhalter, standardmäßig die aktuelle curryierte Funktion* @return {Function} die Funktion nach dem Curry*/ Funktion Curry (fn, Länge = fn. Länge, Halter = Curry) { returniere _curry.call(diese,fn,Länge,Halter,[],[]) } /** * Übertragungsfunktion* @param fn ursprüngliche Funktion des Curryings* @param length Anzahl der von der ursprünglichen Funktion benötigten Parameter* @param holder empfangener Platzhalter* @param args empfangene Parameterliste* @param holders empfangene Platzhalterpositionsliste* @return {Function} Funktion zum Fortsetzen des Curryings oder Endergebnis*/ Funktion _curry(fn,Länge,Inhaber,Argumente,Inhaber){ Rückgabefunktion (..._args) { //Kopieren Sie die Parameter, um Verwirrung durch mehrere Operationen an derselben Funktion zu vermeiden. let params = args.slice(); //Kopieren Sie die Platzhalterpositionsliste und fügen Sie die neu hinzugefügten Platzhalter hier ein let _holders = holders.slice(); //Parameter durchlaufen, Parameter anhängen oder placeholders_args.forEach((arg,i)=>{ ersetzen //Vor dem eigentlichen Parameter steht ein Platzhalter. Ersetzen Sie den Platzhalter durch den eigentlichen Parameter if (arg !== holder && holders.length) { let index = Inhaber.Shift(); _holders.splice(_holders.indexOf(index),1); Parameter[Index] = Argument; } //Vor dem eigentlichen Parameter steht kein Platzhalter. Füge den Parameter an die Parameterliste an, sonst wenn (arg !== holder && !holders.length) { Parameter.push(arg); } //Der Platzhalter wird übergeben. Wenn vorher kein Platzhalter vorhanden ist, notieren Sie die Position des Platzhalters, sonst wenn (arg === holder && !holders.length) { Parameter.push(arg); _holders.push(Parameterlänge - 1); } //Der übergebene Platzhalter. Davor steht ein Platzhalter. Lösche die ursprüngliche Position des Platzhalters. Sonst wenn (arg === holder && holders.length) { Inhaber.Shift(); } }); // Die ersten Längendatensätze in Parametern enthalten keine Platzhalter, führen Sie die Funktion aus, wenn (params.length >= length && params.slice(0,length).every(i=>i!==holder)){ gibt fn.apply(diese, Parameter) zurück; }anders{ returniere _curry.call(dies,fn,Länge,Inhaber,Parameter,_Inhaber) } } } Überprüfen Sie es: sei fn = Funktion(a, b, c, d, e) { Konsole.log([a, b, c, d, e]); } let _ = {}; // Platzhalter definieren let _fn = curry(fn,5,_); // Curry die Funktion, spezifiziere die benötigte Anzahl an Parametern und spezifiziere die benötigten Platzhalter _fn(1, 2, 3, 4, 5); // drucken: 1,2,3,4,5 _fn(_, 2, 3, 4, 5)(1); // drucken: 1,2,3,4,5 _fn(1, _, 3, 4, 5)(2); // drucken: 1,2,3,4,5 _fn(1, _, 3)(_, 4,_)(2)(5); // drucken: 1,2,3,4,5 _fn(1, _, _, 4)(_, 3)(2)(5); // drucken: 1,2,3,4,5 _fn(_, 2)(_, _, 4)(1)(3)(5); // drucken: 1,2,3,4,5 Bisher haben wir eine 7. Implementierung von Shallow Copy und Deep Copy Deep Copy und Shallow Copy sind nur für Referenzdatentypen wie 7.1 Der Unterschied zwischen Shallow Copy und Deep CopyOberflächliche Kopie: Erstellen Sie ein neues Objekt, das eine exakte Kopie der Eigenschaftswerte des Originalobjekts aufweist. Wenn die Eigenschaft von einem primitiven Typ ist, wird der Wert des primitiven Typs kopiert. Wenn die Eigenschaft von einem Referenztyp ist, wird die Speicheradresse kopiert. Wenn eines der Objekte die Eigenschaft des Referenztyps ändert, wirkt sich dies auf das andere Objekt aus. Tiefes Kopieren: Kopiert ein Objekt vollständig aus dem Speicher und öffnet einen neuen Bereich im Heap-Speicher, um es zu speichern. Auf diese Weise wirkt sich eine Änderung des Kopierwerts nicht auf das alte Objekt aus. Flache Kopierimplementierung: Methode 1: Funktion flachKopie(Ziel, Ursprung){ für (Element im Ursprung lassen) Ziel[Element] = Ursprung[Element]; Rücklaufziel; } Andere Methoden (integrierte API): (1) Objekt.zuweisen var obj={a:1,b:[1,2,3],c:function(){console.log('ich bin c')}} var tar={}; Objekt.assign(tar,obj); Natürlich ist diese Methode nur für Objekttypen geeignet. Wenn es sich um ein Array handelt, können Sie (2) Array.Prototyp.Scheibe var arr=[1,2,[3,4]]; var newArr = arr.slice(0); Array.prototype.concat var arr=[1,2,[3,4]]; var newArr=arr.concat(); (3) Array.prototype.concat var arr=[1,2,[3,4]]; var newArr=arr.concat(); Der Test ist derselbe wie oben (Assign wird mit Objekten getestet, Slice Concat wird mit Arrays getestet). Es ist besser zu verstehen, wenn man die Konzepte Shallow Copy und Deep Copy kombiniert. Deep Copy-Implementierung: Methode 1: In das JSON-Format konvertieren und dann analysieren Methode 2: // Implementierung der Deep-Copy-Rekursionsfunktion deepCopy(newObj,oldObj){ für(var k in altesObj){ let item = altesObj[k] // Bestimmen, ob es ein Array, ein Objekt oder ein einfacher Typ ist? wenn(Elementinstanz des Arrays){ neuesObjekt[k]=[] deepCopy(neuesObjekt[k],Element) }sonst wenn(Elementinstanz des Objekts){ neuesObj[k]={} deepCopy(neuesObjekt[k],Element) }else{ //Einfacher Datentyp, weise direkt newObj[k]=item zu } } } 8. Handschriftlich anrufen, beantragen, binden8.1 Handschriftlicher AnrufFunction.prototype.myCall=function(context=window){ // Funktionsmethode, wird also auf das Function-Prototypobjekt geschrieben if(typeof this !=="function"){ // Wenn hier tatsächlich nichts erforderlich ist, wird automatisch ein Fehler geworfen throw new Error("keine Funktion") } const obj = Kontext || Fenster // Hier können Sie die ES6-Methode verwenden, um Standardwerte für Parameter hinzuzufügen. Der globale Bereich des strikten Modus von js ist undefiniert obj.fn=this //das ist der aufrufende Kontext, dies ist eine Funktion, verwenden Sie diese Funktion als Methode von obj const arg=[...arguments].slice(1) //Das erste ist obj, also löschen Sie es und konvertieren Sie das Pseudo-Array in ein Array res=obj.fn(...arg) delete obj.fn // Wenn das Löschen fehlschlägt, werden immer mehr Kontextattribute zurückgegeben. } // Verwendung: f.call(obj,arg1) Funktion f(a,b){ konsole.log(a+b) console.log(dieser.Name) } lass obj = { Name:1 } f.myCall(obj,1,2) //Andernfalls zeigt dies auf das Fenster obj.greet.call({name: 'Spike'}) //Die Ausgabe ist Spike 8.2 Handschriftliches Anwenden (Argumente [dies, [Parameter 1, Parameter 2 ...]])Function.prototype.myApply = function(context) { // Pfeilfunktionen haben niemals ein Argumentobjekt! ! ! ! ! Sie können hier keine Pfeilfunktion schreiben let obj=context||window obj.fn=dies const arg=arguments[1]||[] //Wenn Parameter vorhanden sind, ist das Ergebnis ein Array let res=obj.fn(...arg) obj.fn löschen Rückgabewert } Funktion f(a,b){ konsole.log(a,b) console.log(dieser.Name) } lass obj = { Name: „Zhang San“ } f.myApply(obj,[1,2]) //Argumente[1] 8.3 Handschriftliche Bindungdieser.Wert = 2 var foo = { Wert: 1 }; var bar = function(name, alter, schule){ console.log(name) // 'Ein' console.log(Alter) // 22 console.log(Schule) // 'Homeschooling-Universität' } var result = bar.bind(foo, 'An') //Setzt einige Parameter 'An' vorab result(22, 'Home University') //Dieser Parameter wird mit den voreingestellten Parametern zusammengeführt und in bar eingefügt. Einfache Version Function.prototype.bind = Funktion(Kontext, ...äußereArgs) { var fn = dies; return function(...innerArgs) { //Gibt eine Funktion zurück, ...rest ist der Parameter, der beim eigentlichen Aufruf übergeben wird return fn.apply(context,[...outerArgs, ...innerArgs]); //Gibt die Funktion zurück, die dies geändert hat, //Parameter zusammenführen} } Gründe, warum „Neu“ fehlgeschlagen ist: Beispiel: // einen Kontext deklarieren let thovino = { Name: 'thovino' } // Deklariere einen Konstruktor let eat = function (food) { dieses.Essen = Essen console.log(`${this.name} isst ${this.food}`) } eat.prototype.sayFuncName = Funktion () { console.log('Funktionsname: essen') } // binden let thovinoEat = eat.bind(thovino) let instance = new thovinoEat('orange') //Eigentlich wird Orange in Thovino eingefügt console.log('instance:', instance) // {} Die generierte Instanz ist ein leeres Objekt Wenn der Funktion thovinoEat (...innerArgs) { eat.call(thovino, ...äußereArgs, ...innereArgs) } Wenn der neue Operator den dritten Schritt Mit anderen Worten: Wir möchten, dass der neue Operator in Neue und vererbbare Versionen Function.prototype.bind = Funktion (Kontext, ...äußereArgumente) { lass das = dies; Funktion res (...innerArgs) { wenn (diese Instanz von res) { // Wenn der neue Operator ausgeführt wird // Hier zeigt dies auf das einfache leere Objekt, das von new selbst im dritten Schritt des neuen Operators erstellt wurde {} das.aufrufen(dies, ...äußereArgs, ...innereArgs) } anders { // Normales Binden that.call(Kontext, ...äußereArgs, ...innereArgs) } } res.prototype = dieser.prototype //! ! ! Rückgabewert } 9. Manuelle Implementierung neuerNeue Prozesstextbeschreibung:
Funktion Person(Name,Alter){ dieser.name=Name this.age=Alter } Person.prototype.sayHi=function(){ console.log('Hallo! Ich bin '+this.name) } let p1=neue Person('neue Person',18) ////Manuell neue implementieren Funktion erstellen(){ let obj={} //Konstruktor abrufen let fn=[].shift.call(arguments) //Argumenteobjekt in ein Array umwandeln. Argumente sind kein Array, sondern ein Objekt! ! ! Diese Methode entfernt das erste Element des Argument-Arrays, ! ! Dabei spielt es keine Rolle, ob das leere Array mit Elementen gefüllt ist oder nicht, es hat keinen Einfluss auf das Ergebnis von Argumenten oder let arg = [].slice.call(arguments,1) obj.__proto__ = fn.prototype let res = fn.apply(obj, arguments) //Ändern Sie dies, um der Instanz Methoden und Eigenschaften hinzuzufügen //Stellen Sie sicher, dass ein Objekt zurückgegeben wird (falls fn kein Konstruktor ist) Rückgabetyp von res==='Objekt'?res:obj } let p2=erstellen(Person,'Person',19) p2.sagHallo() Detail: [].shift.call(arguments) kann auch wie folgt geschrieben werden: let arg=[...Argumente] let fn=arg.shift() //Aktiviert Argumente zum Aufrufen von Array-Methoden, der erste Parameter ist der Konstruktor obj.__proto__=fn.prototype //Ändern Sie diesen Zeiger, um der Instanz Methoden und Attribute hinzuzufügen let res=fn.apply(obj,arg) 10. Handgeschriebenes Versprechen (oft getestet mit promise.all, promise.race)// Drei Zustände, die in der Promise/A+ Spezifikation spezifiziert sind const STATUS = { PENDING: 'ausstehend', ERFÜLLT: 'erfüllt', ABGELEHNT: „abgelehnt“ } Klasse MeinVersprechen { // Der Konstruktor erhält einen Ausführungs-Callback constructor(executor) { this._status = STATUS.PENDING // Versprechen Sie den anfänglichen Status this._value = undefined // dann den Rückrufwert this._resolveQueue = [] // Erfolgswarteschlange, ausgelöst durch „Resolve“ this._rejectQueue = [] // Fehlerwarteschlange, ausgelöst durch „Reject“ //Verwende die Pfeilfunktion um dies zu beheben (die Auflösungsfunktion wird im Executor ausgelöst, sonst kann sie nicht gefunden werden) const resolve = Wert => { const laufen = () => { // Die Promise/A+ Spezifikation legt fest, dass der Promise-Status nur von ausstehend bis erfüllt ausgelöst werden kann wenn (this._status === STATUS.PENDING) { this._status = STATUS.FULFILLED // Status ändern this._value = value // Aktuellen Wert für anschließenden Rückruf speichern // Rückruf auflösen, während (this._resolveQueue.length) { const Rückruf = this._resolveQueue.shift() Rückruf(Wert) } } } // Kapseln Sie den Resolve-Callback-Vorgang in eine Funktion ein und setzen Sie diese in „setTimeout“, um die Funktion für asynchrone Promise-Aufrufe zu implementieren (Mikrotask in der Spezifikation, Makrotask hier) setTimeout(ausführen) } // Das Gleiche wie „Resolve“ const reject = Wert => { const laufen = () => { wenn (this._status === STATUS.PENDING) { this._status = STATUS.ABGELEHNT this._value = Wert während (this._rejectQueue.length) { const Rückruf = this._rejectQueue.shift() Rückruf(Wert) } } } setTimeout(ausführen) } // Wenn new Promise() aufgerufen wird, wird der Executor sofort ausgeführt und resolve und reject werden übergeben Vollstrecker (lösen, ablehnen) } // then-Methode, die einen erfolgreichen Rückruf und einen fehlgeschlagenen Rückruf empfängt function then(onFulfilled, onRejected) { // Gemäß der Spezifikation wird der Parameter von then, wenn es sich nicht um eine Funktion handelt, ignoriert, der Wert weitergegeben und der Kettenaufruf weiter ausgeführt typeof onFulfilled !== 'function' ? onFulfilled = value => value : null typeof onRejected !== 'Funktion' ? onRejected = Fehler => Fehler : null // gibt dann ein neues Versprechen zurück returniere neues MyPromise((auflösen, ablehnen) => { const resolveFn = Wert => { versuchen { const x = beiErfüllt(Wert) // Klassifiziere den Rückgabewert. Wenn es ein Promise ist, warte auf die Änderung des Promise-Status, andernfalls löse direkt auf x Instanz von MyPromise? x.then(auflösen, ablehnen) : auflösen(x) } Fehler abfangen { ablehnen(Fehler) } } } } const rejectFn = Fehler => { versuchen { const x = beiAbgelehnt(Fehler) x Instanz von MyPromise? x.then(auflösen, ablehnen) : auflösen(x) } Fehler abfangen { ablehnen(Fehler) } } Schalter (this._status) { Fall STATUS.PENDING: this._resolveQueue.push(resolveFn) dies._rejectQueue.push(rejectFn) brechen; Fall STATUS.ERFÜLLT: auflösenFn(diesen._Wert) brechen; Fall STATUS.ABGELEHNT: rejectFn(dieser._Wert) brechen; } }) } fangen (ablehnenFn) { gib dies zurück.dann(undefiniert, rejectFn) } // promise.finally-Methode finally(callback) { gib dies zurück.dann(Wert => MyPromise.resolve(callback()).dann(() => Wert), Fehler => { MyPromise.resolve(callback()).then(() => Fehler) }) } // statische Auflösungsmethode statische Auflösung(Wert) { Rückgabewert: Instanz von MyPromise? Wert: neues MyPromise (auflösen => auflösen(Wert)) } // statische Ablehnungsmethode statische Ablehnung (Fehler) { returniere neues MyPromise((auflösen, ablehnen) => ablehnen(Fehler)) } // statische alle Methoden static all(promiseArr) { lass count = 0 let ergebnis = [] returniere neues MyPromise((auflösen, ablehnen) => { wenn (!promiseArr.length) { Rückgabewert (Ergebnis) } promiseArr.fürEach((p, i) => { MyPromise.resolve(p).then(Wert => { zählen++ Ergebnis[i] = Wert wenn (Anzahl === promiseArr.Länge) { Lösung (Ergebnis) } }, Fehler => { ablehnen(Fehler) }) }) }) } // Statische Race-Methode static race(promiseArr) { returniere neues MyPromise((auflösen, ablehnen) => { promiseArr.fürJeden(p => { MyPromise.resolve(p).then(Wert => { Auflösung (Wert) }, Fehler => { ablehnen(Fehler) }) }) }) } } 11. Handgeschriebenes natives AJAXSchritt:
Im Laufe der Geschichte wurde XML jedoch eliminiert und durch JSON ersetzt. Nachdem Sie die Eigenschaften und Methoden verstanden haben, schreiben Sie die einfachste GET-Anfrage gemäß den AJAX-Schritten. Version 1.0: myButton.addEventListener('klicken', Funktion () { ajax() }) Funktion ajax() { let xhr = new XMLHttpRequest() //Instanziieren, um die Methode xhr.open('get', 'https://www.google.com') aufzurufen //Parameter 2, URL. Parameter drei: asynchron xhr.onreadystatechange = () => { //Diese Funktion wird aufgerufen, wenn sich die Eigenschaft readyState ändert. if (xhr.readyState === 4) { //Der aktuelle Status des XMLHttpRequest-Proxys. if (xhr.status >= 200 && xhr.status < 300) { //200-300 Anfrage erfolgreich let string = request.responseText //Die Methode JSON.parse() wird verwendet, um die JSON-Zeichenfolge zu analysieren und einen JavaScript-Wert oder ein Objekt zu konstruieren, das durch die Zeichenfolge let object = JSON.parse(string) beschrieben wird. } } } request.send() //Wird verwendet, um tatsächlich eine HTTP-Anfrage zu stellen. GET-Anfrage ohne Parameter} Versprechenserfüllung Funktion Ajax (URL) { const p = neues Versprechen((lösen, ablehnen) => { let xhr = neue XMLHttpRequest() xhr.open('erhalten', URL) xhr.onreadystatechange = () => { wenn (xhr.readyState == 4) { wenn (xhr.status >= 200 und xhr.status <= 300) { auflösen(JSON.parse(xhr.responseText)) } anders { reject('Anforderungsfehler') } } } xhr.send() //HPPT-Anfrage senden}) Rückkehr p } let url = "/data.json" ajax(url).dann(res => console.log(res)) .catch(Grund => console.log(Grund)) 12. Handschriftliche Drosselung und Anti-Shake-Funktion Sowohl die Funktionsdrosselung als auch die Funktion „Anti-Shake“ zielen darauf ab, die Ausführungshäufigkeit von Funktionen zu begrenzen. Sie sind eine Lösung zur Leistungsoptimierung, wie z. B. Beispiel : (Verwenden Sie es, wenn eine kontinuierliche Bewegung aufgerufen werden muss, legen Sie ein Zeitintervall fest), wie beim Ziehen von DOM. Wenn Sie Debounce verwenden, entsteht ein Gefühl der Blockierung, da es nur einmal ausgeführt wird, wenn es stoppt. Zu diesem Zeitpunkt sollten Sie Throttling verwenden und es innerhalb eines bestimmten Zeitraums mehrmals ausführen, was viel reibungsloser läuft. Anti-Shake: bedeutet, dass eine Funktion nur einmal innerhalb von n Sekunden nach Auslösen eines Ereignisses ausgeführt werden kann. Wenn das Ereignis innerhalb von n Sekunden erneut ausgelöst wird, wird die Ausführungszeit der Funktion neu berechnet. Beispiel : (Wird nicht aufgerufen, wenn es kontinuierlich ausgelöst wird, sondern nach einer gewissen Zeit nach der Auslösung aufgerufen), wie bei der Nachahmung der Baidu-Suche sollte Anti-Shake verwendet werden. Wenn ich kontinuierlich eingebe, wird keine Anforderung gesendet; wenn ich für eine gewisse Zeit keine Eingabe mache, wird einmal eine Anforderung gesendet; wenn ich weniger als diese Zeitspanne weiter eingebe, wird die Zeit neu berechnet und es wird keine Anforderung gesendet. 12.1 Anti-Shake-ImplementierungFunktion Entprellung(fn, Verzögerung) { wenn(Typ von fn!=='Funktion') { throw new TypeError('fn ist keine Funktion') } let timer; // Einen Timer verwalten Rückgabefunktion () { var _this = this; // Holen Sie sich das this des Debounce-Ausführungsbereichs (das Objekt, an das die ursprüngliche Funktion gemountet ist) var args = Argumente; wenn (Zeitgeber) { Zeitüberschreitung löschen(Timer); } Timer = setzeTimeout(Funktion () { fn.apply(_this, args); // Verwenden Sie „apply“, um auf das Objekt zu zeigen, das „debounce“ aufruft, was gleichbedeutend ist mit „_this.fn(args);“. }, Verzögerung); }; } // Anruf input1.addEventListener('keyup', entprellung(() => { konsole.log(eingabe1.wert) }), 600) 12.2 Implementierung der DrosselungFunktion Drosselklappe(fn, Verzögerung) { lass den Timer; Rückgabefunktion () { var _this = dies; var args = Argumente; wenn (Zeitgeber) { zurückkehren; } Timer = setzeTimeout(Funktion () { fn.apply(_this, args); // Hier empfängt args die Parameter der von außen zurückgegebenen Funktion und Argumente können nicht verwendet werden // fn.apply(_this, arguments); Hinweis: Chrome 14 und Internet Explorer 9 akzeptieren immer noch keine arrayähnlichen Objekte. Wenn ihnen ein arrayähnliches Objekt übergeben wird, wird eine Ausnahme ausgelöst. timer = null; // Lösche den Timer nach der Ausführung von fn nach der Verzögerung. Zu diesem Zeitpunkt ist der Timer falsch und der Gashebel kann den Timer eingeben}, Verzögerung) } } div1.addEventListener('ziehen', Drosselklappe((e) => { Konsole.log(e.offsetX, e.offsetY) }, 100)) 13. Handschriftliches Versprechen, Bilder hochzuladenFunktion getData(URL) { returniere neues Promise((lösen, ablehnen) => { $.ajax({ URL (URL = URL = URL), Erfolg(Daten) { auflösen (Daten) }, Fehler(Fehler) { ablehnen (Fehler) } }) }) } const url1 = "./data1.json" const url2 = "./data2.json" const url3 = "./data3.json" getData(url1).then(data1 => { konsole.log(daten1) returniere getData(url2) }).dann(data2 => { konsole.log(data2) returniere getData(url3) }).dann(data3 => konsole.log(data3) ).catch(err => console.error(fehler) ) 14. Die Funktion gibt eine Zahl pro Sekunde aus (!!! Diese Frage wurde dieser Tage im Campus-Rekrutierungsinterview von ByteDance gestellt. Es wurde gefragt, welche Var ausgegeben wird. Warum kann sie in „let“ geändert werden? ES6: Implementierung mit dem Prinzip des Let-Block-Bereichs for(let i=0;i<=10;i++){ //Mit var drucken ist 11 setzeTimeout(()=>{ konsole.log(i); },1000*i) } Schreiben ohne let: Das Prinzip besteht darin, einen Blockebenenbereich mit einer sofort ausgeführten Funktion zu erstellen für(var i = 1; i <= 10; i++){ (Funktion (i) { setzeTimeout(Funktion () { konsole.log(i); }, 1000 * ich) })(ich); } 15. 10 Tags erstellen und die entsprechenden Seriennummern beim Anklicken einblenden?var ein für (lass i = 0; i < 10; i++) { a=Dokument.Element erstellen('a') a.innerHTML=i+'<br>' a.addEventListener('klicken',Funktion(e){ console.log(this) //das ist das aktuell angeklickte <a> e.preventDefault() //Wenn diese Methode aufgerufen wird, wird das Standardereignisverhalten nicht mehr ausgelöst. //Wenn Sie beispielsweise nach der Ausführung dieser Methode auf einen Link (ein Tag) klicken, springt der Browser nicht zur neuen URL. Wir können event.isDefaultPrevented() verwenden, um zu bestimmen, ob diese Methode (für dieses Ereignisobjekt) aufgerufen wurde. Warnung(i) }) const d = Dokument.QuerySelector('div') d.appendChild(a) //append hängt das Element an ein bestehendes Element an. } 16. Implementieren Sie das Abonnement und die Veröffentlichung von Ereignissen (eventBus). Implementieren Sie die EventBus-Klasse mit Klasse EventBus { ein(Ereignisname, Listener) {} aus(Ereignisname, Listener) {} einmal (Ereignisname, Listener) {} Auslöser(Ereignisname) {} } const e = neuer EventBus(); // fn1 fn2 e.on('e1', fn1) e.einmal('e1', fn2) e.trigger('e1') // fn1() fn2() e.trigger('e1') // fn1() e.aus('e1', fn1) e.trigger('e1') // null erreichen: //Klasse class EventBus deklarieren { Konstruktor() { this.eventList = {} //Erstellen Sie ein Objekt zum Sammeln von Ereignissen} //Ereignis veröffentlichen $on(eventName, fn) { //Feststellen, ob der Ereignisname veröffentlicht wurde? Veröffentlichung hinzufügen: Veröffentlichung erstellen und hinzufügen this.eventList[eventName] ? this.eventList[Ereignisname].push(fn) : (diese.eventList[eventName] = [fn]) } //Ereignis abonnieren $emit(eventName) { if (!eventName) throw new Error('Bitte geben Sie den Ereignisnamen ein') //Abonnementparameter abrufen const data = [...arguments].slice(1) wenn (diese.eventList[eventName]) { diese.eventList[eventName].forEach((i) => { versuchen { i(...data) //Abfrageereignisse} catch (e) { console.error(e + 'eventName:' + eventName) //Fehler während der Ausführung sammeln} }) } } //Einmal ausführen$once(eventName, fn) { const _this = dies Funktion onceHandle() { fn.apply(null, Argumente) _this.$off(eventName, onceHandle) //Überwachung nach erfolgreicher Ausführung abbrechen} dies.$on(Ereignisname, onceHandle) } //Abmelden $off(eventName, fn) { //Alle Abonnements stornieren, wenn keine Parameter übergeben werden if (!arguments.length) { Rückgabe (diese.Ereignisliste = {}) } //Wenn eventName als Array übergeben wird, mehrere Abonnements stornieren, if (Array.isArray(eventName)) { returniere Ereignisname.fürJedes((Ereignis) => { dies.$aus(Ereignis, fn) }) } //Alle Warteschlangen unter dem Ereignisnamen abbrechen, wenn fn nicht übergeben wird, if (arguments.length === 1 || !fn) { this.eventList[Ereignisname] = [] } //Brechen Sie die Funktion unter dem Ereignisnamen ab this.eventList[Ereignisname] = this.eventList[Ereignisname].filter( (f) => f !== fn ) } } const event = neuer EventBus() sei b = Funktion (v1, v2, v3) { console.log('b', v1, v2, v3) } sei a = Funktion () { Konsole.log('a') } Ereignis.$einmal('Test', a) Ereignis.$auf('test', b) Ereignis.$emit('test', 1, 2, 3, 45, 123) Ereignis.$aus(['test'], b) Ereignis.$emit('test', 1, 2, 3, 45, 123) Dies ist das Ende des Artikels über die hochfrequente Handschrift von js für Front-End-Interviews. Weitere verwandte Inhalte zur hochfrequenten Handschrift von js finden Sie in den vorherigen Artikeln von 123WORDPRESS.COM oder durchsuchen Sie die verwandten Artikel unten weiter. Ich hoffe, Sie werden 123WORDPRESS.COM in Zukunft unterstützen! Das könnte Sie auch interessieren:
|
<<: Zusammenfassung verschiedener Replikationsmethoden für die MySQL Master-Slave-Replikation
>>: So lösen Sie das domänenübergreifende Front-End-Problem mithilfe des Nginx-Proxys
Da es zu mühsam ist, jedes Mal das Installationst...
Inhaltsverzeichnis Einführung in den NFS-Dienst W...
Inhaltsverzeichnis Vorwort Einführung JavaScript ...
Eine Vektorwelle <svg viewBox="0 0 560 20...
Inhaltsverzeichnis 1. Zweck 2. Grammatik 3. Üben ...
Hintergrund In der Gruppe werden einige Studieren...
Inhaltsverzeichnis 1. Prototyp-Modus Beispiel 1 B...
Dieser Artikel veranschaulicht anhand von Beispie...
1. Die erste Methode besteht darin, den Befehl un...
Inhaltsverzeichnis 1. Requisiten Übergeordnetes E...
Die Methode zum Abrufen der Zeigerposition in Jav...
Die feste IP-Adresse des Centos-DVD1-Versionssyst...
1. Netzwerkoptimierung YSlow hat 23 Regeln. Diese...
Inhaltsverzeichnis 1. Einführung in Gojs 2. Gojs ...
Code kopieren Der Code lautet wie folgt: <div ...