What is JMobile JavaScript?

Forstå JavaScripts call() Metode Dybtgående

12/02/2023

Rating: 4.1 (15392 votes)

JavaScript er et sprog fyldt med fleksibilitet og kraftfulde værktøjer, der giver udviklere mulighed for at skrive effektiv og genanvendelig kode. En af disse essentielle værktøjer er call() metoden. Denne metode er ikke blot en måde at kalde en funktion på; den tilbyder en unik evne til at manipulere den kontekst, som en funktion udføres i. At forstå call() er afgørende for enhver JavaScript-udvikler, da den åbner døre til mere avanceret programmering, især når det kommer til genbrug af metoder og håndtering af this nøgleordet.

What is call() method in JavaScript?
The call() method is a predefined JavaScript method. It can be used to invoke (call) a method with an object as an argument (parameter). With call(), an object can use a method belonging to another object. This example calls the fullName method of person, using it on person1: This example calls the fullName method of person, using it on person2:

I denne artikel vil vi udforske call() metodens dybder, fra dens grundlæggende syntaks til dens praktiske anvendelser. Vi vil starte med at afmystificere this nøgleordet, som er fundamentalt for at forstå, hvordan call() fungerer. Derefter vil vi dykke ned i, hvordan call() muliggør metodegenbrug og giver dig kontrol over udførelseskonteksten for dine funktioner. Gør dig klar til at udvide din JavaScript-viden og mestre et af sprogets mest alsidige værktøjer.

Indholdsfortegnelse

Hvad er 'this' i JavaScript? En Grundlæggende Forståelse

Før vi kan forstå call() metoden fuldt ud, er det bydende nødvendigt at have en solid forståelse af this nøgleordet i JavaScript. this er et af de mest misforståede koncepter i JavaScript, primært fordi dets værdi ikke er statisk, men dynamisk bestemt af den måde, en funktion kaldes på. Kort sagt refererer this til et objekt, men hvilket objekt det refererer til, afhænger af konteksten.

Forskellige Kontekster for 'this':

  • 'this' alene: Når this bruges alene i den globale udførelseskontekst (uden for enhver funktion eller objekt), refererer det til det globale objekt. I browsere er det typisk window-objektet. I Node.js er det global-objektet.

    console.log(this === window); // I browseren: true
  • 'this' i en funktion (ikke-strict mode): Også i en almindelig funktion, der kaldes som en standalone-funktion (ikke som en metode på et objekt), vil this som standard pege på det globale objekt (window i browsere). Dette er ofte en kilde til forvirring og potentielle fejl, da det kan give uønskede sideeffekter.

    function showThis() {
    console.log(this);
    }
    showThis(); // I browseren: window-objektet
  • 'this' i en funktion (strict mode): I JavaScripts strikte tilstand (aktiveret med 'use strict';), er reglerne for this strengere. Hvis en funktion kaldes uden en eksplicit kontekst, vil this være undefined. Dette hjælper med at fange fejl, der ellers ville pege på det globale objekt.

    'use strict';
    function showThisStrict() {
    console.log(this);
    }
    showThisStrict(); // undefined
  • 'this' i en objektmetode: Når en funktion defineres som en metode på et objekt og kaldes via det objekt, refererer this til selve det objekt, som metoden tilhører. Dette er den mest intuitive brug af this.

    const person = {
    firstName: "John",
    lastName: "Doe",
    fullName: function() {
    return this.firstName + " " + this.lastName;
    }
    };
    console.log(person.fullName()); // John Doe (this refererer til 'person' objektet)
  • 'this' i en event: I en event-handler, der er knyttet til et DOM-element, refererer this til det element, der modtog eventen.

    <button onclick="console.log(this)">Klik mig</button> // this refererer til button-elementet
  • 'this' med call(), apply(), og bind(): Disse metoder er designet specifikt til at give dig mulighed for at sætte værdien af this eksplicit. Dette er præcis, hvad vi vil udforske i dybden med call() metoden, da den giver dig fuld kontrol over udførelseskonteksten.

Det er vigtigt at huske, at this er et nøgleord og ikke en variabel. Du kan ikke ændre værdien af this direkte ved tildeling, men kun ved at ændre den måde, funktionen kaldes på, eller ved at bruge metoder som call(), apply() eller bind(). Denne dynamiske natur gør this kraftfuld, men kræver også en præcis forståelse for at undgå uventede resultater.

Hvad er 'call()' Metoden?

call() metoden er en foruddefineret JavaScript-metode, der findes på alle funktioner. Dens primære formål er at invokere (kalde) en funktion med en specifik værdi for this og individuelle argumenter. Det betyder, at du kan 'låne' en metode fra ét objekt og bruge den på et andet objekt, som om metoden tilhørte det andet objekt.

Forestil dig, at du har en funktion, der er defineret som en metode på et bestemt objekt. Med call() kan du kalde denne funktion, men specificere et helt andet objekt som dens this-kontekst. Dette er utrolig nyttigt for metodegenbrug og for at skrive mere modulær og fleksibel kode.

Syntaksen for call() er som følger:

funktion.call(thisArg, arg1, arg2, ...);
  • thisArg: Dette er det objekt, som this nøgleordet skal referere til inde i funktionen, når den udføres. Det er den afgørende del af call(), da den eksplicit sætter konteksten.
  • arg1, arg2, ...: Disse er de argumenter, der skal sendes til funktionen. De skal angives individuelt, adskilt af kommaer.

Denne evne til at kontrollere this-konteksten er, hvad der gør call() så kraftfuld. Uden call() (og dens søskende apply() og bind()) ville this altid være bundet til den måde, funktionen oprindeligt blev kaldt på, hvilket ville begrænse metodegenbrug betydeligt.

Eksempler på Genbrug af Metoder med 'call()'

Lad os se på, hvordan call() metoden kan bruges til at genbruge metoder på forskellige objekter. Dette er et klassisk eksempel, der illustrerer call()'s kernefunktionalitet.

Antag, at vi har et person-objekt med en fullName-metode:

const person = {
fullName: function() {
return this.firstName + " " + this.lastName;
}
};

Denne fullName-metode er designet til at arbejde med et objekt, der har firstName og lastName egenskaber. Inde i fullName refererer this til det objekt, som metoden kaldes på. Hvis vi kalder person.fullName(), vil this referere til person-objektet, og resultatet ville være "undefined undefined", da person-objektet ikke har disse egenskaber direkte, men kun metoden.

Nu har vi to andre objekter, person1 og person2, som indeholder de nødvendige firstName og lastName egenskaber:

const person1 = {
firstName:"John",
lastName: "Doe"
};

const person2 = {
firstName:"Mary",
lastName: "Doe"
};

Vi ønsker at bruge person.fullName-metoden til at generere det fulde navn for både person1 og person2, uden at skulle duplikere fullName-metoden på hvert enkelt objekt. Dette er her call() kommer ind i billedet.

Brug af 'call()' med 'person1':

// Dette vil returnere "John Doe":
const fullNameJohn = person.fullName.call(person1);
console.log(fullNameJohn); // Output: John Doe

I dette eksempel kalder vi fullName-metoden, som er defineret på person-objektet, men vi bruger call() til at angive, at this inde i fullName-metoden skal pege på person1-objektet. Derfor, når fullName udføres, vil this.firstName være person1.firstName (som er "John"), og this.lastName vil være person1.lastName (som er "Doe"). Resultatet er en korrekt sammensætning af navnet fra person1.

Brug af 'call()' med 'person2':

// Dette vil returnere "Mary Doe":
const fullNameMary = person.fullName.call(person2);
console.log(fullNameMary); // Output: Mary Doe

På samme måde kan vi genbruge den samme fullName-metode for person2. Ved at kalde person.fullName.call(person2) sætter vi this-konteksten for fullName til at være person2-objektet. Følgelig returneres "Mary Doe".

Disse eksempler demonstrerer tydeligt den fleksibilitet og metodegenbrug, som call() metoden tilbyder. Du kan skrive en generisk metode én gang og derefter anvende den på forskellige objekter, forudsat at disse objekter har de nødvendige egenskaber, som metoden forventer at finde via this.

'call()' Metoden med Argumenter

Ud over at sætte this-konteksten kan call() metoden også acceptere argumenter, som sendes direkte til den funktion, der kaldes. Disse argumenter angives efter det første argument (thisArg) og adskilles af kommaer. Dette gør call() endnu mere alsidig, da du ikke kun kan styre konteksten, men også sende specifikke data til funktionen.

Lad os udvide vores tidligere eksempel. Forestil dig, at vores fullName-metode nu også skal inkludere information om den by og det land, personen kommer fra. Vi kan ændre funktionen til at acceptere disse som argumenter:

const person = {
fullName: function(city, country) {
return this.firstName + " " + this.lastName + ", from " + city + ", " + country;
}
};

Nu kan vi kalde denne funktion på person1 og person2 og samtidig sende de ekstra by- og landoplysninger:

const person1 = {
firstName:"John",
lastName: "Doe"
};

const person2 = {
firstName:"Mary",
lastName: "Doe"
};

// Kalder fullName for person1 med by og land som argumenter
const johnLocation = person.fullName.call(person1, "Oslo", "Norway");
console.log(johnLocation); // Output: John Doe, from Oslo, Norway

// Kalder fullName for person2 med by og land som argumenter
const maryLocation = person.fullName.call(person2, "Paris", "France");
console.log(maryLocation); // Output: Mary Doe, from Paris, France

Som det fremgår af eksemplet, fungerer call() perfekt med yderligere argumenter. Det første argument (person1 eller person2) sætter this-konteksten, og de efterfølgende argumenter ("Oslo", "Norway", "Paris", "France") sendes som parametre til fullName-funktionen i den rækkefølge, de er angivet.

Dette understreger call() metodens alsidighed. Den giver dig fuld kontrol over både den kontekst, funktionen udføres i, og de data, den modtager. Denne kombination er utrolig kraftfuld for at skrive genanvendelig og dynamisk JavaScript-kode.

Praktiske Anvendelser af 'call()'

call() metoden er ikke kun et teoretisk koncept; den har mange praktiske anvendelser i hverdags-JavaScript-udvikling. Her er nogle af de mest almindelige scenarier, hvor call() skinner igennem:

1. Metodeudlån (Method Borrowing)

Den mest intuitive og hyppige anvendelse af call() er metodeudlån, som vi allerede har set. Dette giver dig mulighed for at genbruge metoder, der oprindeligt er defineret på én type objekt, på en anden type objekt, der måske ikke har den pågældende metode, men som har de nødvendige egenskaber. Et klassisk eksempel er at bruge array-metoder på array-lignende objekter.

For eksempel er arguments-objektet inde i en funktion et array-lignende objekt, men det har ikke alle array-metoder som forEach, map eller filter. Du kan dog "låne" disse metoder fra Array.prototype og anvende dem på arguments ved hjælp af call():

function listArguments() {
console.log("Argumenter:");
// Bruger forEach-metoden fra Array.prototype på arguments-objektet
Array.prototype.forEach.call(arguments, function(arg, index) {
console.log(`Argument ${index}: ${arg}`);
});
}

listArguments(10, "hello", true);
// Output:
// Argumenter:
// Argument 0: 10
// Argument 1: hello
// Argument 2: true

På samme måde kan call() bruges til at konvertere et array-lignende objekt (som en NodeList fra DOM) til et ægte array ved hjælp af Array.prototype.slice:

const divs = document.querySelectorAll('div'); // En NodeList (array-lignende)
const divArray = Array.prototype.slice.call(divs); // Konverterer til et ægte array

console.log(Array.isArray(divs)); // false
console.log(Array.isArray(divArray)); // true

Dette er en meget almindelig og kraftfuld teknik i front-end udvikling.

2. Arv og Konstruktører

I ældre JavaScript-mønstre, før ES6-klasser blev udbredt, blev call() ofte brugt til at implementere pseudo-klassisk arv. Specifikt til at kalde en forældrekonstruktør fra en børnekonstruktør. Dette sikrer, at forældreklassens egenskaber initialiseres korrekt på børneobjektet.

function Person(name, age) {
this.name = name;
this.age = age;
}

function Employee(name, age, salary) {
// Kalder Person-konstruktøren med Employee-instansen som 'this'
Person.call(this, name, age);
this.salary = salary;
}

const emp = new Employee("Alice", 30, 50000);
console.log(emp.name); // Alice
console.log(emp.age); // 30
console.log(emp.salary); // 50000

Her sikrer Person.call(this, name, age), at name og age egenskaberne fra Person-konstruktøren bliver sat på den nye Employee-instans (som this refererer til inde i Employee-konstruktøren).

3. Funktioner, der forventer en specifik 'this'-kontekst

Nogle biblioteker eller API'er kan levere funktioner, der forventer at blive kaldt med en specifik this-kontekst. call() giver dig mulighed for at opfylde dette krav, selvom funktionen ikke er en direkte metode på det ønskede objekt.

Samlet set giver call() dig enestående kontrol over udførelseskonteksten for dine funktioner, hvilket er essentielt for at skrive robust, genanvendelig og fleksibel JavaScript-kode.

Ofte Stillede Spørgsmål om 'call()'

Her er nogle af de mest almindelige spørgsmål, der opstår, når man arbejder med call() metoden i JavaScript.

Kan 'call()' bruges med pilfunktioner (arrow functions)?

Ja, du kan kalde en pilfunktion ved hjælp af call(), men det er vigtigt at forstå, at call()ikke vil ændre værdien af this inde i pilfunktionen. Pilfunktioner har en leksikalsk this-binding, hvilket betyder, at de arver this fra deres omgivende (enclosing) scope på det tidspunkt, hvor de defineres, og denne binding kan ikke ændres af call(), apply() eller bind(). Argumenterne vil dog stadig blive sendt korrekt.

const myArrowFunction = (arg1) => {
console.log("Inside arrow function, this is:", this); // this vil være det globale objekt i browseren
console.log("Argument:", arg1);
};

const someObject = { name: "Test" };
myArrowFunction.call(someObject, "Hello");
// Output:
// Inside arrow function, this is: Window (i browseren, eller global i Node.js)
// Argument: Hello

Som du kan se, forbliver this det globale objekt (Window i browseren) selvom vi forsøgte at sætte det til someObject med call(). Argumentet "Hello" blev dog korrekt videregivet. Dette er en afgørende forskel mellem pilfunktioner og traditionelle funktioner.

Påvirker 'call()' ydeevnen i JavaScript?

For de fleste almindelige applikationer og brugsscenarier er ydeevnepåvirkningen ved at bruge call() metoden ubetydelig. JavaScript-engines er stærkt optimerede. Selvom et direkte metodekald (f.eks. object.method()) i teorien kan være marginalt hurtigere, er forskellen så minimal, at den sjældent er relevant, medmindre du arbejder med yderst performance-kritiske loops, der udføres millioner af gange. I langt de fleste tilfælde er klarheden, fleksibiliteten og metodegenbrugen, som call() tilbyder, langt vigtigere end en potentiel mikroskopisk ydeevneforskel.

Hvorfor er 'this' så vigtigt at forstå med 'call()'?

Forståelsen af this er absolut central for at kunne bruge call() effektivt. call()'s primære formål er netop at give dig kontrol over, hvad this refererer til inde i funktionen, når den udføres. Hvis du ikke forstår de forskellige måder, this kan bindes på, vil du have svært ved at forudsige resultatet af dine call()-kald eller at fejlfinde, når this ikke er, hvad du forventer. Det er nøglen til at låne metoder, implementere arv og generelt manipulere udførelseskonteksten dynamisk.

Er der alternativer til 'call()' til at sætte 'this'?

Ja, JavaScript tilbyder to andre metoder, der ligner call() i deres evne til at sætte this-konteksten for en funktion: apply() og bind(). Mens denne artikel primært fokuserer på call(), er det værd at nævne dem kort:

  • apply(): Fungerer meget lig call(), men den accepterer argumenter som et array i stedet for individuelle argumenter. Syntaksen er funktion.apply(thisArg, [arg1, arg2, ...]).
  • bind(): Adskiller sig ved, at den ikke kalder funktionen med det samme. I stedet returnerer den en ny funktion, hvor this-konteksten er permanent bundet til den specificerede værdi. Denne nye funktion kan derefter kaldes senere.

Valget mellem disse tre afhænger af dit specifikke behov: Skal funktionen kaldes med det samme (call()/apply()), og hvordan skal argumenter sendes (individuelt eller som array)? Eller skal du have en ny, forudbundet funktion til fremtidig brug (bind())?

Konklusion

call() metoden er et uvurderligt værktøj i JavaScript, der giver dig enestående kontrol over, hvordan dine funktioner udføres. Ved at give dig mulighed for at sætte this-konteksten eksplicit og sende argumenter individuelt, åbner call() op for kraftfuld metodegenbrug og skaber mere fleksible og modulære kodeløsninger. Forståelsen af this nøgleordet og dets dynamiske natur er afgørende for at mestre call().

Uanset om du låner array-metoder til array-lignende objekter, implementerer arvemønstre eller blot ønsker at kalde en funktion med en specifik kontekst, er call() en fundamental del af JavaScript-udviklerens værktøjskasse. Ved at integrere denne viden i din programmeringspraksis kan du skrive renere, mere effektive og mere vedligeholdelsesvenlige JavaScript-applikationer. Fortsæt med at eksperimentere med call() og udforsk dens mange anvendelser for at styrke dine JavaScript-færdigheder yderligere.

Hvis du vil læse andre artikler, der ligner Forstå JavaScripts call() Metode Dybtgående, kan du besøge kategorien Mobil.

Go up