Kein Zugriff auf Objekt
Bobby
- javascript
Moin
ich habe ein komisches Problem.
var coordinates={};
for (var i=0; i < window.mapData.length; i ++)
{
var point=window.mapData[i];
$.getJSON('http://maps.googleapis.com/maps/api/geocode/json?i='+i+'&address='+point.address+'&sensor=false')
.done(function(data)
{
var Ausdruck=/\?i\=([0-9]*?)\&/;
Ausdruck.exec($(this)[0].url);
coordinates[RegExp.$1]=data.results[0].geometry.location;
});
console.info(i);
console.info(coordinates);
console.info(coordinates[0]);
}
console.info(coordinates);
das i wird korrekt ausgegeben. Das coordinates-Object wird an beiden Stellen ordentlich ausgegeben. Ich erhalte aber keinen Zugriff auf coordinates[0]
Was könnte der Grund sein?
Ergebnis:
0
Object {}
undefined
Object {}
Objekte sind wie folgt aufgebaut:
0
Object { lat=51.0939492, lng=13.7021921}
lat
51.0939492
lng
13.7021921
1
Object { lat=51.0806841, lng=13.7099601}
lat
51.0806841
lng
13.7099601
Ich bin echt ratlos.
Gruß Bobby
Hi,
Das coordinates-Object wird an beiden Stellen ordentlich ausgegeben. Ich erhalte aber keinen Zugriff auf coordinates[0]
Was könnte der Grund sein?
Dass dieses *Objekt* keine Eigenschaft namens "0" hat …?
MfG ChrisB
Moin
Dass dieses *Objekt* keine Eigenschaft namens "0" hat …?
ich präzisiere: zu diesem ZEITPUNKT hat das Objekt noch keine Eigenschaft "0". Später dann ja. Es wird nicht auf die Ausführung von $.getJSON gewartet. Nun führe ich alles weitere erst aus wenn ein Ergebnis zurückgeliefert wurde. Und siehe da. Es funktioniert.
Gruß Bobby
Hallo Bobby,
var coordinates={};
console.info(coordinates[0]);
auch wenn dein Problem gelöst ist, du solltest dich schon entscheiden, ob du ein Array oder ein Objekt hast.
Gruß, Jürgen
Moin
auch wenn dein Problem gelöst ist, du solltest dich schon entscheiden, ob du ein Array oder ein Objekt hast.
ähm:
Des Weiteren kann man einen numerischen Literal oder String-Literal für den Namen der Eigenschaft benutzen oder Objekte ineinander verschachteln:
var car = { manyCars: {a: "Saab", "b": "Jeep"}, 7: "Mazda" };
console.log(car.manyCars.b); // Jeep
console.log(car[7]); // Mazda
Merke:
var foo = {a: "alpha", 2: "zwei"};
console.log(foo.a); // alpha
console.log(foo[2]); // zwei
//console.log(foo.2); // Error: fehlende ) nach der Argumentliste
//console.log(foo[a]); // Error: a ist nicht definiert
console.log(foo["a"]); // alpha
console.log(foo["2"]); // zwei
Quelle: https://developer.mozilla.org/de/docs/JavaScript/Guide/Werte_Variablen_und_Literale#Array-Literale
Gruß Bobby
Hallo Bobby,
danke für die Nachhilfe, aber du hast mir immer noch nicht erklärt, was das
var coordinates={};
^
...
console.info(coordinates[0]);
^
hier soll.
Gruß, Jürgen
danke für die Nachhilfe, aber du hast mir immer noch nicht erklärt, was das
[code lang=javascript]
var coordinates={};
^
...
console.info(coordinates[0]);
Naja, bei
coordinates=[];
coordinates[7]=...;
coordinates[9999]=...;
coordinates[99999999]=...;
macht es durchaus Sinn, das als Objekt und nicht als Array zu deklarieren.
Da es bei Ihm die Properties aber fortlaufend sind, hat du recht, daß es eigentlich ein Array sein sollte.
Moin
Naja, bei
coordinates=[];
coordinates[7]=...;
coordinates[9999]=...;
coordinates[99999999]=...;
macht es durchaus Sinn, das als Objekt und nicht als Array zu deklarieren.
Da es bei Ihm die Properties aber fortlaufend sind, hat du recht, daß es eigentlich ein Array sein sollte.
Und genau so war es auch gedacht. Wnen mal coordinaten nicht gefunden wurden, soll auch kein Eintrag erfolgen.
Gruß Bobby
Moin
danke für die Nachhilfe,
Sollte um Gottes Willen keine Nachhilfe sein. Das würde ich mir nie herausnehmen. Es hätte ja sein können, dass ich einem Irrtum unterliege und hab mal geteilt wo ich mein Wissen zum Teil her hab
aber du hast mir immer noch nicht erklärt, was das
var coordinates={};
^
...
console.info(coordinates[0]);
^
Ja sicher hätte ich auch direkt ein Array verwenden können. da ich aber alle anderen Variablen im Object-Stil geschrieben habe, hab ich das für coordinates einfach auch gemacht... Ist doch kein Beinbruch...
Gruß Bobby
--
-> Für jedes Problem gibt es eine Lösung, die einfach, sauber und falsch ist! <-
### Henry L. Mencken ###
-> Nicht das Problem macht die Schwierigkeiten, sondern unsere Sichtweise! <-
## Viktor Frankl ###
ie:{ br:> fl:{ va:} ls:< fo:) rl:( n4:( de:> ss:) ch:? js:( mo:} sh:) zu:)
Hallo,
Klar, Arrays in JavaScript sind nur besondere Objects. Letztlich sind die Elemente eines Arrays Objekteigenschaften, und die numerischen Indizes sind letztlich String-Eigenschaftsnamen. Arrays haben aber eine zusätzliche Magie und zusätzliche Eigenschaften und Methoden, weil sie von Array.prototype erben. Die will man auch meist benutzen. Zum Beispiel, wenn man die Liste durchlaufen will (length-Eigenschaft!).
[code lang=javascript]var car = { manyCars: {a: "Saab", "b": "Jeep"}, 7: "Mazda" };
Dieses Beispiel ist zwar syntaktisch korrekt, ergibt aber keinen Sinn (warum sollte man das tun?). Natürlich kann man numerische Eigenschaftsnamen verwenden – JavaScript wandelt sie letztlich in Strings um. objekt[5] ist identisch zu objekt["5"] (Array-Magie einmal ausgenommen).
Mathias
Hi,
$.getJSON('http://maps.googleapis.com/maps/api/geocode/json?i='+i+'&address='+point.address+'&sensor=false')
.done(function(data)
{
var Ausdruck=/?i=([0-9]*?)&/;
Ausdruck.exec($(this)[0].url);
Was ist »this« hier? Ich nehme an, $() ist jQuery und du wrappst ein Element damit. Dann wäre url eine Elementeigenschaft. Dann könntest du auch gleich »this.url« schreiben.
Ich kenne in HTML kein Element, das standardmäßig eine Eigenschaft url hat, aber vielleicht hsat du sie angelegt.
coordinates[RegExp.$1]=data.results[0].geometry.location;
Noch ein Hinweis:
http://de.selfhtml.org/javascript/objekte/regexp.htm#exec@title=exec gibt dir die Resultate freundlicherweise als Array zurück. Das Element mit dem Index 0 liefert den gesamten Treffer, die folgenden Indizes die Teiltreffer.
RegExp.$1 funktioniert zwar, ist aber ein Relikt aus grauer Vorzeit. Es wurde nicht standardisiert und ist schlechter Stil. Resultate eines Funktionsaufrufs an einem globalen Objekt abholen – das widerspricht sämtlichen Grundlagen der robusten Programmierung.
Mathias
Moin
Was ist »this« hier? Ich nehme an, $() ist jQuery und du wrappst ein Element damit. Dann wäre url eine Elementeigenschaft. Dann könntest du auch gleich »this.url« schreiben.
$(this) bezieht sich auf das getJSON Objekt. Dies hat sehr wohl eine Eigenschaft URL.
RegExp.$1 funktioniert zwar, ist aber ein Relikt aus grauer Vorzeit. Es wurde nicht standardisiert und ist schlechter Stil. Resultate eines Funktionsaufrufs an einem globalen Objekt abholen – das widerspricht sämtlichen Grundlagen der robusten Programmierung.
Siehst du, da bin ich wohl stehengeblieben... danke für den hilfreichen Hinweis.
Gruß Bobby
Was ist »this« hier? Ich nehme an, $() ist jQuery und du wrappst ein Element damit. Dann wäre url eine Elementeigenschaft. Dann könntest du auch gleich »this.url« schreiben.
$(this) bezieht sich auf das getJSON Objekt. Dies hat sehr wohl eine Eigenschaft URL.
getJSON ist eine Funktion, gut auch das ist ein Objekt, aber die hat vermutlich keine Eigenschaft url. Auch ist das egal, es zählt allein, an welchem Objekt das Callback gespeichert bzw. gerufen wird.
Ich würde vermuten, das Callback wird mit den restlichen Optionen in einem Objekt gespeichert und dann wird an diesem das Callback gerufen. Das würde die Eigenschaft url erklären.
Das wäre dann aber nicht dokumentiert und du kannst dich nicht darauf verlassen, daß das so bleibt.
Moin
Was ist »this« hier? Ich nehme an, $() ist jQuery und du wrappst ein Element damit. Dann wäre url eine Elementeigenschaft. Dann könntest du auch gleich »this.url« schreiben.
$(this) bezieht sich auf das getJSON Objekt. Dies hat sehr wohl eine Eigenschaft URL.
getJSON ist eine Funktion, gut auch das ist ein Objekt, aber die hat vermutlich keine Eigenschaft url. Auch ist das egal, es zählt allein, an welchem Objekt das Callback gespeichert bzw. gerufen wird.
Ich würde vermuten, das Callback wird mit den restlichen Optionen in einem Objekt gespeichert und dann wird an diesem das Callback gerufen. Das würde die Eigenschaft url erklären.
Das wäre dann aber nicht dokumentiert und du kannst dich nicht darauf verlassen, daß das so bleibt.
Ergebnis der Ausgabe: $(this)
accepts
Object { *="*/*", text="text/plain", html="text/html", mehr...}
async
true
contentType
"application/x-www-form-urlencoded; charset=UTF-8"
contents
Object { xml=RegExp, html=RegExp, json=RegExp, mehr...}
converters
Object { text html=true, * text=String(), text json=function(), mehr...}
crossDomain
true
dataType
"json"
dataTypes
["text", "json"]
flatOptions
Object { url=true, context=true}
global
true
hasContent
false
isLocal
false
jsonp
"callback"
processData
true
responseFields
Object { xml="responseXML", text="responseText", json="responseJSON"}
type
"GET"
url
"http://maps.googleapis....n&sensor=false"
jsonpCallback
function()
xhr
$c()
das ist das normale XMLHTTPRequest-Objekt (bzw. jqXHR-Objekt) über das das Ajax abläuft. Sollte also funktionieren.
Gruß Bobby
das ist das normale XMLHTTPRequest-Objekt (bzw. jqXHR-Objekt) über das das Ajax abläuft. Sollte also funktionieren.
Und wo steht, daß das jqXHR Objekt eine Eigenschaft url hat? Das habe ich nicht gefunden.
Aber der Sinn des jqXHR Objektes ist ja folgender:
For backward compatibility with XMLHttpRequest, a jqXHR object will expose the following properties and methods:
readyState
status
statusText
responseXML and/or responseText when the underlying request responded with xml and/or text, respectively
setRequestHeader(name, value) which departs from the standard by replacing the old value with the new one rather than concatenating the new value to the old one
getAllResponseHeaders()
getResponseHeader()
statusCode()
abort()
und genau das sehe ich nicht in deiner Ausgabe.
Und wo steht, daß das jqXHR Objekt eine Eigenschaft url hat? Das habe ich nicht gefunden.
Ein Fall von schlechter Dokumentation. Aus dem Code geht es hervor: Das Konfigurationsobjekt ist der Callback-Context, und das hat eine url-Eigenschaft.
https://github.com/jquery/jquery/blob/2.1.0/src/ajax.js#L407-L410
https://github.com/jquery/jquery/blob/2.1.0/src/ajax.js#L506-L507
https://github.com/jquery/jquery/blob/2.1.0/src/ajax.js#L755-L756
M.
Und wo steht, daß das jqXHR Objekt eine Eigenschaft url hat? Das habe ich nicht gefunden.
Ein Fall von schlechter Dokumentation. Aus dem Code geht es hervor: Das Konfigurationsobjekt ist der Callback-Context, und das hat eine url-Eigenschaft.
Und selbst wenn es aus dem Code ersichtlich wäre, ist es nicht dokumentiert. Und was in einer API nicht dokumentiert ist, ist nicht für die Benutzung gedacht.
Das ist ja das "Problem" von JS, jeder kann in den Code sehen und Internas echt zu kapseln macht eine Menge Arbeit.
Moin
Und selbst wenn es aus dem Code ersichtlich wäre, ist es nicht dokumentiert. Und was in einer API nicht dokumentiert ist, ist nicht für die Benutzung gedacht.
Das ist ja das "Problem" von JS, jeder kann in den Code sehen und Internas echt zu kapseln macht eine Menge Arbeit.
Ja mag sein. Ich denke aber, dass in Zukunft nicht daran rungeschraubt wird. Und in der eingebundenen JQuery-Bibliothek schon gleich gar nicht. ;)
Aber trotzdem Dank für Eure Hinweise.
Gruß Bobby
Und selbst wenn es aus dem Code ersichtlich wäre, ist es nicht dokumentiert. Und was in einer API nicht dokumentiert ist, ist nicht für die Benutzung gedacht.
Es ist durchaus hier erwähnt, im Rahmen des context-Settings:
http://api.jquery.com/jQuery.ajax/
»context
Type: PlainObject
This object will be made the context of all Ajax-related callbacks. By default, the context is an object that represents the ajax settings used in the call ($.ajaxSettings merged with the settings passed to $.ajax). [Dann wird erklärt, wie man den Kontext selbst setzen kann.]«
Der Default-Fall ist auch durchaus getestet:
https://github.com/jquery/jquery/blob/2.1.0/test/unit/ajax.js#L409-L421
Und ich vermute, der Haupt-Anwendungsfall ist dieser hier:
https://github.com/jquery/jquery/blob/2.1.0/test/unit/ajax.js#L151-L183
Im Fehlerfall nimmt man die Settings und gibt sie einfach nochmal an jQuery.ajax().
Den context-Kram zumindest würde ich nicht als Interna bezeichnen.
Ich hätte das mit einem weiteren Parameter für den Callback gelöst. Ansonsten kommt man, wenn man this sinnvoll setzt, nicht an die Settings.
jQuery setzt an vielen Stellen this auf irgendein obskures Objekt. In fast allen Fällen würde ich davon abraten, es zu nutzen. Und meistens kann man es auch.
Bei der Objektorientierten Programmierung will man meist selbst this verwenden, um das aktuelle Objekt zu referenzieren. Dazu werden die Callback-Funktionen gebunden.
Stellen in jQuery, wo man this vermeiden sollte:
$('#foo').on('click', function(event) {
alert(this); // Pfui
alert(event.currentTarget); // Pendant
alert(event.target); // Manchmal will man auch das
});
// Ja, das ist die Parameterreihenfolge! Bei Array#forEach,
// Array#some usw. sowie in allen vernünftigen Sprachen und Bibliotheken ist sie umgekehrt.
$('.foo').each(function(index, element) {
alert(this); // Pfui
alert(element); // Pendant
});
Hier kann man es dummerweise nicht vermeiden:
$('.foo').filter(function(index) {
alert(this); // Das Elementobjekt
});
jQuery ist in dieser Hinsicht ziemlich kaputt.
</threaddrift>
Mathias
Es ist durchaus hier erwähnt, im Rahmen des context-Settings:
http://api.jquery.com/jQuery.ajax/
Den default context hatte ich eigentlich gesucht, aber nicht gefunden.
Dann nehme ich meine Bemerkung zurück, es ist also durchaus legitim hier auf die url Eigenschaft der Settings zuzugreifen.
Moin
Den default context hatte ich eigentlich gesucht, aber nicht gefunden.
Dann nehme ich meine Bemerkung zurück, es ist also durchaus legitim hier auf die url Eigenschaft der Settings zuzugreifen.
Nun bin ich aber froh, dass auch das geklärt ist, und meine Lösung sinnvoll und richtig ist (übrigens: siehe meiner Signatur). In diesem Sinne, Dank an Euch für die rege Diskussion. So ist dieses Forum effektiv!
Gruß Bobby
Om nah hoo pez nyeetz, Bobby!
(übrigens: siehe meine Signatur).
Ich find 11 auch viel schöner als 12.
Matthias
Moin
Ich find 11 auch viel schöner als 12.
Chat schöner als JS??? Mir erschließt sich dein Pot gerade nicht... :/
Gruß Bobby
Om nah hoo pez nyeetz, Bobby!
Ich find 11 auch viel schöner als 12.
Chat schöner als JS??? Mir erschließt sich dein Pot gerade nicht... :/
Zähl mal, was in deiner Signatur 11 mal vorkommt und möglicherweise eigentlich 12 mal vorkommen sollte. Schön, dass es dich trotzdem zum Grübeln anregte.
Matthias
Moin
Zähl mal, was in deiner Signatur 11 mal vorkommt und möglicherweise eigentlich 12 mal vorkommen sollte. Schön, dass es dich trotzdem zum Grübeln anregte.
Na klar regt mich das zum nachdenken an. Ich reflektiere sehr oft die Anmerkungen anderer. Man lernt ja nie aus. ;)
Du sprichst in Rätseln... meintest du das fehlende "#"-Zeichen?
Gruß Bobby
Om nah hoo pez nyeetz, Bobby!
Du sprichst in Rätseln... meintest du das fehlende "#"-Zeichen?
Genau.
Matthias
Hi,
Ich find 11 auch viel schöner als 12.
Chat schöner als JS???
Wenn, dann js schöner als mo.
Oder fängst Du etwa mit Index 1 an?
cu,
Andreas
Moin
Wenn, dann js schöner als mo.
Oder fängst Du etwa mit Index 1 an?
hihi.. ich hatte mal außerhalb des Informatikindex gedacht. Da fang ich mit 1 Apfel an und zähle dann weiter. Weil 0 Äpfel ja nix sind. In der Informatik hast du aber selbstverständlich recht. ;)
Gruß Bobby
Und ich vermute, der Haupt-Anwendungsfall ist dieser hier:
https://github.com/jquery/jquery/blob/2.1.0/test/unit/ajax.js#L151-L183
Im Fehlerfall nimmt man die Settings und gibt sie einfach nochmal an jQuery.ajax().
Mag sein, aber intuitiv finde ich das nicht.
Den context-Kram zumindest würde ich nicht als Interna bezeichnen.
Wieso nicht? Wenn du meinst, daß es ja explizit in der Doku steht, gebe ich dir recht.
Sonst ist aber der context eines Callbacks von außen nicht ersichtlich, wenn man ihn nicht selbst von außen festlegt.
Ich hätte das mit einem weiteren Parameter für den Callback gelöst. Ansonsten kommt man, wenn man this sinnvoll setzt, nicht an die Settings.
Warum nicht? Die liegen (hier und im unittestfall) im Scope des Callbacks.
jQuery setzt an vielen Stellen this auf irgendein obskures Objekt.
Ja, gut, aber irgendwo müssen sie ihr Callback ja speichern. Wenn sie sich über das wo noch Gedanken machen und das auch dokumentieren finde ich das in Ordnung.
Ich hätte in diesem Fall nicht das Optionobjekt genommen, aber das ist nur meine Meinung.
In fast allen Fällen würde ich davon abraten, es zu nutzen.
Kommt darauf an, hier hätte ich es auch nicht verwendet. Hinzu kommt meistens auch noch deine nächste Bemerkung:
Bei der Objektorientierten Programmierung will man meist selbst this verwenden, um das aktuelle Objekt zu referenzieren.
Aber abraten, wenn der Defaultcontext definiert ist? Warum?
$('#foo').on('click', function(event) {
alert(this); // Pfui
alert(event.currentTarget); // Pendant
alert(event.target); // Manchmal will man auch das
});
Klar, event.currentTarget ist viel intuitiver, in der Doku ist es auch nur angedeutet(als Beispiel), oder ich habe es wieder übersehen, aber warum pfui?
> ~~~javascript
// Ja, das ist die Parameterreihenfolge! Bei Array#forEach,
> // Array#some usw. sowie in allen vernünftigen Sprachen und Bibliotheken ist sie umgekehrt.
> $('.foo').each(function(index, element) {
> alert(this); // Pfui
> alert(element); // Pendant
> });
this ist element? Ja, daß finde ich auch merkwürdig, wie hier das Optionobjekt.
Hier kann man es dummerweise nicht vermeiden:
$('.foo').filter(function(index) {
alert(this); // Das Elementobjekt
});
Naja, vermeiden schon, du hast den index und ein Array. Aber hier steht es sogar wieder explizit in der Doku.
Du hast aber recht, hier gehört das Element als Parameter an die Funktion.
> jQuery ist in dieser Hinsicht ziemlich kaputt.
Was heißt kaputt? Soweit ich das jetzt sehe, haben die sich tatsächlich bei jedem Callback gedanken über den Context gemacht.
Ich hatte ja anfangs vermutet, der ist hier zufällig das Optionobjekt geworden, weil sie das Callback zufällig an diesem gespeichetrt haben.
Aber dein oben erwähnter Haupt-Anwendungsfall macht ja durchaus Sinn, auch wenn ich das nicht unbedingt schön finde.
Wenn du meinst, der Context ist von außen ohne Doku sowieso nicht ersichtlich und man hätte diesen von daher besser aufs global object gesetzt, dann bin ich bei dir.
Ich hätte das mit einem weiteren Parameter für den Callback gelöst. Ansonsten kommt man, wenn man this sinnvoll setzt, nicht an die Settings.
Warum nicht?
Wie komm ich sonst daran?
Klar, ich kann Funktionen so verschachteln, dass ich die Settings, die ich an $.ajax() übergebe, im Success- und Error-Handler zur Verfügung habe. Aber:
Die liegen (hier und im unittestfall) im Scope des Callbacks.
Im Fall von https://github.com/jquery/jquery/blob/2.1.0/test/unit/ajax.js#L151-L183 gibt es außer »this« keine Möglichkeit, auf das letztlich verwendete Settings-Objekt zuzugreifen. Das Settings-Objekt ist in keiner Variable in einem der äußeren Scopes gespeichert.
Wenn ich $.get(), $.getJSON(), $.post() usw. anstatt der Low-Level-Funktion $.ajax() verwende, dann lässt kann ich das erzeugte Settings-Objekt auch nicht per Closure den Handlern zugänglich machen, denn es wird intern erzeugt.
Bei der Objektorientierten Programmierung will man meist selbst this verwenden, um das aktuelle Objekt zu referenzieren.
Aber abraten, wenn der Defaultcontext definiert ist? Warum?
Sagte ich ja: Weil man den Kontext selbst kontrollieren will. Stichwort Function Binding.
Klar, event.currentTarget ist viel intuitiver, in der Doku ist es auch nur angedeutet(als Beispiel), oder ich habe es wieder übersehen, aber warum pfui?
Der Kontext von Event-Handlern ist seit langem so in »DOM 0« (sprich seit Netscape 2.0) definiert. Klar, das ist äußerst robust – jQuery hat es nicht erfunden, sondern macht dasselbe, was bei element.onevent = function() { alert(this) }
bzw. element.addEventListener('event', function() { alert(this) })
passiert. Es ist allerdings nicht sprechend und bricht, sobald irgendwie anders der Kontext gesetzt wird. Den Kontext von Event-Handlern auf das View-Objekt zu setzen ist das erste, was man bei objektorientierter GUI-Programmierung tut. Das machen alle Frontend-JavaScript-Frameworks, die ich kenne.
Was heißt kaputt? Soweit ich das jetzt sehe, haben die sich tatsächlich bei jedem Callback gedanken über den Context gemacht.
Ja, aber warum überhaupt? Dass eine Bibliothek wie jQuery, welche einen sehr begrenzten Bereich der JavaScript-Programmierung abdeckt, den Funktionskontext mit Bedeutung versieht, ist ein großes Problem. Man sollte es den Entwicklern überlassen, du auf Basis von jQuery High-Level-Anwendungen entwickeln.
Es gibt verschiedene Möglichkeiten, Low-Level-jQuery mit eigenem Code zu verdrahten:
Closures sind wohl die häufigste Technik, aber sie skaliert nicht gut. Partial Application ist wenigen bekannt. Im OOP-Bereich bleibt nur Function Binding.
Wenn du meinst, der Context ist von außen ohne Doku sowieso nicht ersichtlich und man hätte diesen von daher besser aufs global object gesetzt, dann bin ich bei dir.
Ja. Der Kontext sollte gar nicht forciert werden. Dann ist er derjenige, der vom Entwickler gesetzt wurde, bzw. als Fallback window oder undefined (im ES5 Strict Mode).
Mathias
Wie komm ich sonst daran?
Im einfachsten (und ich würde behaupten, das ist der Normalfall) so
obj = {
loadData: function() {
$.ajax({
url: "meine_url",
error: this.errHandler.bind(this)
});
},
errHandler: function() {
this.mfkt();
}
};
Klar, ich kann Funktionen so verschachteln, dass ich die Settings, die ich an $.ajax() übergebe, im Success- und Error-Handler zur Verfügung habe. Aber:
- Funktionen zu verschachteln erzeugt schwer lesbaren Code
Aber selbst wenn man die Settings erst generisch zusammenbasteln muss, sehe ich da kein Problem
obj = {
mfkt: function() {
var ajaxoptions;
ajaxoptions = {
url: url("data/errorWithText.php"),
error: this.errHandler().bind(this, ajaxoptions);
};
loadData(ajaxoptions);
},
loadData: function(ajaxoptions) {
$.ajax(ajaxoptions);
},
err: function(ajaxoptions) {
this.loadData(ajaxoptions);
}
};
Im Fall von https://github.com/jquery/jquery/blob/2.1.0/test/unit/ajax.js#L151-L183 gibt es außer »this« keine Möglichkeit, auf das letztlich verwendete Settings-Objekt zuzugreifen. Das Settings-Objekt ist in keiner Variable in einem der äußeren Scopes gespeichert.
Die Settings sind in der temporären Variablen {url:..., error:...} im Scope der anonymen Funktion, welche an asyncTest übergeben wird, gespeichert.
Eine Referenz auf dieses temporary wird der ajax-Funktion übergeben, welche es dann als Context des Errorhandlers bindet.
Dieser temporären Variablen noch ein deklaratives var zu verpassen macht es jetzt nicht komplexer.
Wenn ich $.get(), $.getJSON(), $.post() usw. anstatt der Low-Level-Funktion $.ajax() verwende, dann lässt kann ich das erzeugte Settings-Objekt auch nicht per Closure den Handlern zugänglich machen, denn es wird intern erzeugt.
Aber dann habe ich die Parameter die ich an diese Funktionen übergebe und lasse es mir ein weiteres mal intern erzeugen.
Bei der Objektorientierten Programmierung will man meist selbst this verwenden, um das aktuelle Objekt zu referenzieren.
Aber abraten, wenn der Defaultcontext definiert ist? Warum?Sagte ich ja: Weil man den Kontext selbst kontrollieren will. Stichwort Function Binding.
Das "Aber abraten, wenn der Defaultcontext definiert ist? Warum?" war hier nicht auf
Bei der Objektorientierten Programmierung will man meist selbst this verwenden, um das aktuelle Objekt zu referenzieren.
bezogen, dann ist es ja klar, dass man es nicht nutzen kann. War schlecht ersichtlich, gebe ich zu.
Der Kontext von Event-Handlern ist seit langem so in »DOM 0« (sprich seit Netscape 2.0) definiert.
Bei DOM 0 Event-Handlern ist der Context klar ersichtlich, ich selbst speichere ja den Eventhandler am element
element.onevent = function() { alert(this) }
Es wird also mit element.onevent() gerufen.
Bei addEventListener ist es definiert https://developer.mozilla.org/en-US/docs/Web/API/EventTarget.addEventListener#The_value_of_this_within_the_handler.
(Wobei ich die Beschreibung dort schon grenzwertig finde.)
Sinnvoller Weise kompatibel und jedes Framework muss es wiederum definieren.
Aber das Beispiel zeigt es doch ganz gut. jQuery hat sich hier auch für Kompatibilität entschieden. Das ist doch erst mal gut.
Ja, aber warum überhaupt? ... Man sollte es den Entwicklern überlassen, die auf Basis von jQuery High-Level-Anwendungen entwickeln.
Den Context bestimmt immer derjenige, welcher den Handler übergibt.
Nur wenn ihm dieser egal ist, bestimmt es das Framework, dann kann man diesen aber auch ignorieren.
Es sei denn, dieser, durch das Framework bestimmte Context, ist ein wichtiger Bestandteil, an den man anders nicht (vernünftig) herankommt. Wie in deinem letzten Beispiel.
Also dort fehlt das Element als Parameter, nicht der Defaultcontext als Element ist das Problem.
Diesen kann nutzen wer will, man sollte ihn aber nicht nutzen MÜSSEN.
Klar, wenn man von vornherein darauf verzichtet hätte hier einen Context sinnvoll zu setzen, wäre das aufgefallen.
Und wo steht, daß das jqXHR Objekt eine Eigenschaft url hat? Das habe ich nicht gefunden.
Sorry, du hast natürlich völlig Recht. jqXHR hat keine url-Eigenschaft, sondern das Konfigurationsobjekt. this zeigt nicht auf ein jqXHR-Objekt, sondern auf das Konfigurationsobjekt! Das jqXHR-Objekt wird als erster Parameter an den Callback übergeben.
$(this) bezieht sich auf das getJSON Objekt. Dies hat sehr wohl eine Eigenschaft URL.
this verweist auf das jqXHR-Objekt, das ist ein von jQuery erzeugtes Objekt. Ja, das hat eine url-Eigenschaft.
Dann kannst du aber immer noch this.url schreiben. $(this)[0]
gibt dir das, was du hineingibst, wieder zurück. $(123.456)[0]
ergibt 123.456 usw.
Wenn man einfach nur auf eine Eigenschaft eines simplen Objektes zugreifen will, das einem auch direkt vorliegt, braucht man nicht jQuery verwenden.
var objekt = { foo: 'bar' };
alert(objekt.foo);
Mathias