Tim Tepaße: Typecasting und Prototypen von Objekten

Beitrag lesen

Hallo Mathias, zonk,

Primitive Werte »haben« genauso Methoden insofern, dass sie intern ständig in die entsprechenden Objekte »umgewandelt« werden.
Das hatte ich bei der Antwort von Tim anders verstanden (Stichworte: eigene toString()-Methoden, toPrimitive()).

Vielleicht hab ich mich da missverständlich ausgedrückt. ToPrimitive, ToString, ToBoolean sind Hilfs-Funktionen innerhalb des ECMAScript-Interpreters. Manchmal rufen diese bei Objekten deren tatsächlich in JS definierte Methoden auf. Bei primitiven Werten jedoch nicht.

Nein, jeder Function-Scope hat sein eigenes arguments-Objekt, siehe Link im letzten Posting.
Wenn das gar nicht standardisiert ist, kann man eigentlich keine Aussagen darüber machen. In JScript, nur als Beispiel, könnte es ja ganz anders sein.

Im ECMAScript-Standard ist genau definiert, dass diese nur ein einem eigenen Exekutionskontext existierten. Wie der jeweils lokale Stack genau umgesetzt ist, nicht. arguments existiert nur in diesem lokalen Scope.

Ich denke mal eher, Java, Ruby oder Python wären in dieser Hinsicht mit JavaScript vergleichbare Sprachen, mit denen kenne ich mich aber überhaupt nicht aus. (Tiiim!)

In Python ist alles ein Objekt. Früher gab es zwar eine Unterschied zwischen Types und Classes; das war aber vor meiner Zeit. Sprich damit definiert man ein Objekt:

>>> s = "eins zwei drei"

(Die „>>>“ hier kommen von der interaktiven Python Shell.)

Es ist vom Typ String ...

~~~python

type(s)

<type 'str'>

  
... der gleichzeitig die Klasse für das Objekt bildet:  
  
  ~~~python

>>> s.__class__  

  <type 'str'>

Typen existieren immer noch, sind aber mit Klassen vereint. Hier macht sich jemand die Mühe, das auseinander zu dröseln, aber im wesentlich kann man sich sagen: „Alles ist ein Objekt“.

Als Objekt hat man immer Zugriff auf alle Eigenschaften, ob nun Properties oder Methoden:

~~~python

dir(s)

['add', 'class', 'contains', 'delattr', 'doc', 'eq',
  'ge', 'getattribute', 'getitem', 'getnewargs', 'getslice',
  'gt', 'hash', 'init', 'le', 'len', 'lt', 'mod',
  'mul', 'ne', 'new', 'reduce', 'reduce_ex', 'repr',
  'rmod', 'rmul', 'setattr', 'str', 'capitalize', 'center',
  'count', 'decode', 'encode', 'endswith', 'expandtabs', 'find', 'index',
  'isalnum', 'isalpha', 'isdigit', 'islower', 'isspace', 'istitle', 'isupper',
  'join', 'ljust', 'lower', 'lstrip', 'partition', 'replace', 'rfind', 'rindex',
  'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines',
  'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']

  
Ausdrücke wie Sting-Konkatenation wird intern auf die Methoden mit den komischen Unterstrichen des Objektes umgesetzt:  
  
  ~~~python

>>> s + " vier"  

  'eins zwei drei vier'  
  >>> s.__add__(" vier")  
  'eins zwei drei vier'

Sprich: Objekte sind selbst für die Implementierung von Operatoren zuständig und können diese damit überladen.

In Ruby ist es ähnlich. Objekt:

~~~ruby s = "eins zwei drei"
  s.class        # Ergibt 'String'

  
Sämtliche Methoden:  
  
  ~~~ruby
"bla".methods  
  [method, send, %, rindex, between?, reject, []=, split, <<, object_id, strip,  
  size, singleton_methods, downcase, gsub!, count, succ!, __send__, downcase!,  
  intern, member?, squeeze!, equal?, taint, *, next, find, frozen?,  
  instance_variable_get, each_with_index, rstrip!, each_line, +, kind_of?, sub,  
  slice!, instance_eval, to_a, tr, replace, collect, reverse, all?, type,  
  unpack, entries, lstrip, protected_methods, capitalize, chop!, extend,  
  capitalize!, scan, to_sym, detect, eql?, display, instance_variable_set, zip,  
  each_byte, is_a?, casecmp, hash, gsub, empty?, to_str, map, to_s, tr_s, any?,  
  tr!, class, match, sort, rstrip, tainted?, private_methods, next!, swapcase,  
  min, chomp!, swapcase!, ljust, untaint, find_all, upto, hex, each, sum, id,  
  reverse!, chop, to_i, insert, <, inject, <=>, inspect, delete, dump, ==,  
  tr_s!, >, concat, ===, clone, succ, sort_by, public_methods, strip!, max,  
  rjust, >=, respond_to?, freeze, index, select, <=, slice, oct, __id__, to_f,  
  length, chomp, methods, upcase, partition, =~, sub!, squeeze, upcase!, crypt,  
  delete!, nil?, dup, grep, instance_variables, lstrip!, include?, instance_of?,  
  center, []]

Darunter sind auch Methoden, die woanders Operatoren wären, also fast wie in Python. Nur sind die hier netter benannt. Dank Rubys Syntax sind das hier die gleichen Methoden-Aufrufe:

~~~ruby "Romeo" + " & Julia"  # Ergibt 'Romeo & Julia'
  "Julia".+(" & Romeo") # Ergibt 'Julia & Romeo'

  
In Ruby sind Klassen nicht geschlossen, d.h. man kann wie in Javascript neue Methoden hinzufügen bzw. bereits definierte ersetzen:  
  
  ~~~ruby
class String  
    def +(other)  
      "Nix da!"  
    end  
  end  
  
  puts "Romeo" + " & " + "Julia"   # Ergibt 'Nix da!'

Java kenne ich auch zuwenig, die anderen gar nicht. Soweit ich weiß, ist dort ein String einfach nur ein String.

Soweit ich weiss – mein Java-Wissen ist aber ewig her – arbeitet Java mit String  - (unveränderlich) bzw. StringBuffer-Objekten (veränderlich) realisiert, auch wenn im Quellcode Literale stehen. Die Verbindung mit „+“ ist dadurch realisiert, dass der +-Operator der einzige überladene Operator in Java ist, d.h. für Strings reagiert er anders als für Zahlen. Man möge mich korrigieren, wenn ich Unsinn rede.

(So ganz unter uns: Ich mag die dynamische Variante von Python und Ruby lieber.)

Tim