Avatar billede janus_007 Nybegynder
23. august 2006 - 01:38 Der er 26 kommentarer og
2 løsninger

Påhæft method til property

Jeg har et simpelt objekt med nogle properties i:
function foo()
{
this.foobar = 15;
funtion multiply()
{
return this*2;
}
}
Nu ønsker jeg at kalde min foo med flg.:
myFoo = new foo();
var newfoobar = myFoo.foobar.multiply();
og få 30 retur

Jeg ved godt at nested innerfunction er private til outer og det er sikkert også derfor ovenstående ikke virker *S*

Men hvordan gør jeg det?
Avatar billede softspot Forsker
23. august 2006 - 08:51 #1
function foobar() {
  this.value = 0;
}

foobar.prototype.multiply = function() {
  return this.value * 2;
}

function foo() {
  this.foobar = new foobar();
}

// initier objekt, tildel værdi og beregn
var f = new foo();
f.foobar.value = 15;
f.foobar.multiply();


Jeg kan ikke lige gennemskue om man kan lave en default-attribut på et javascript-objekt, men der kommer sikkert nogle kvalificerede bud fra andre brugere senere... :)
Avatar billede roenving Novice
23. august 2006 - 09:33 #2
>>softspot

-- hvad mener du med en 'default-attribut' ?-)

-- og selv ville jeg altid lave en funktion minimalt fleksibelt:

foobar.prototype.multiply = function(m) {
  return this.value * (!isNaN(m) ? m : 2);
}
Avatar billede softspot Forsker
23. august 2006 - 09:55 #3
Jeg har begået mig en del i VB og COM, så deraf udtrykket. I COM taler man om default attributter/-funktioner som sådan nogle egenskaber der aktiveres på et objekt, hvis man ikke angiver en specifik attribut/funktion (det er lidt noget rod, men praktisk for den dovne programmør). Eksempelvis kan man typisk på et collection-objekt, kalde enten obj(1) eller obj.item(1) for at hente det første element i listen - her er item altså default-funkton på collection-objektet...

Mht. fleksibiliteten af funktionen, så er jeg da tilbøjelig til at være enig (men det lå bare ikke i "opgaven", så derfor tænkte jeg den ikke med i eksemplet).
Den øgede fleksibilitet giver typisk også øget kompleksitet og det er sjældent godt, hvis man skal eksemplificere noget. Du er vel også selv tilhænger af KISS-princippet (synes jeg at erindre)...?
Avatar billede roenving Novice
23. august 2006 - 10:04 #4
Der er ingen problemer i at angive default-værdier, og det gøres da også oftest i javascript-objekter ved at man i constructor-funktionen sætter sådan en værdi, evt. efter en test af parametre:

function myObject(parm1,parm2,parm3){
  this.parm1 = parm1;
  this.parm2 = parm2 ? parm2 : 615;
  this.createDate = new Date();
}
Avatar billede softspot Forsker
23. august 2006 - 10:19 #5
Bemærk at jeg ikke taler om default-parametre til en funktion, men default-funktioner/-attributter på et objekt. Det er vist en COM-feature, som jeg ikke tror er særlig velset i et normalt objektorienteret miljø, så det er forståeligt, hvis det forekommer sært for nogen (jeg aner ikke om du selv har arbejdet med COM, så jeg vil ikke gøre nogle antagelser).

Jeg tror faktisk det vil svare til at definere en toString-funktion på et javascript-objekt, som returnerer værdien af value-attributten (det lader faktisk til at være løsningen :))...

Noget i stil med:

function foobar() {
  this.value = 0;
}

foobar.prototype.toString = function() {
  return this.value;
}

var fb = new foobar();
var valueOfFoobarValue = fb;
Avatar billede mclemens Nybegynder
23. august 2006 - 12:19 #6
function foo()
{
this.foobar = 15;
this.multiply=function(t){
return t*2;
}
}



myFoo = new foo();

var newfoobar = myFoo["foobar"];

newfoobar=myFoo.multiply(newfoobar);

alert(newfoobar);
Avatar billede mclemens Nybegynder
23. august 2006 - 12:25 #7
... eller:

function foo()
{
this.foobar = 15;
this.multiply=function(t){
return t*2;
}
}



myFoo = new foo();

var newfoobar = myFoo.multiply(myFoo["foobar"]);

alert(newfoobar);
Avatar billede roenving Novice
23. august 2006 - 12:28 #8
-- er det ikke nemmere at bruge dot-notation ?-)

myFoo.multiply(myFoo.foobar);
Avatar billede mclemens Nybegynder
23. august 2006 - 12:29 #9
funtion multiply(){return this*2;}
rettet til:
this.multiply=function(t){return t*2;}

og

var newfoobar = myFoo.foobar.multiply();
rettet til:
var newfoobar = myFoo.multiply(myFoo["foobar"]);

... multiply er ikke en function på variablen foobar - men funktionen myFoo.multiply ønskes kørt på variablen myFoo.foobr som den nye variabel newfoobar så tildeles værdien af.

... og så overførsel af t værdien som beregningen skal ske på ...
Avatar billede mclemens Nybegynder
23. august 2006 - 12:31 #10
Update, joh det er det :o)
Avatar billede softspot Forsker
23. august 2006 - 12:31 #11
...men anonyme funktioner har bare den ulempe, at de kommer til at ligge på alle forekomster af objektet foo (prototyper defineres kun et sted og koden ligger altså kun en gang i hukommelsen - ret mig hvis jeg tager fejl).
Avatar billede mclemens Nybegynder
23. august 2006 - 12:52 #12
Hmmm, den del ved jeg ikke noget om - det ved Rønving bedst :)
(er også selv nysgerrig efter om functionen bliver kopieret når det
er en prototype - eller om der blot er en reference til funktionen)
Avatar billede janus_007 Nybegynder
23. august 2006 - 19:54 #13
Hej og tak for alle de svar, men jeg synes ikke rigtigt vi har ramt hovedet på sømmet.
softspot -> i første omgang ser dit forslag korrekt ud, men så ser jeg at du meget simpelt bruger this.value * 2, og... det skal være mere fleksibelt end det.

Det jeg ønsker er... jeg hæfter lige lidt mere på min oprindelige:

function foo()
{
this.foobar = 15;
this.widget = 45;

funtion multiply()
{
return this*2;
}
}

altså... så vil jeg gerne sige
myFoo = new foo();
myFoo.foobar.multiply(); skal gerne give 30
og
myFoo.widget.multiply(); skal gerne give 90

Jeg så på et tidspunkt noget med man laver en inner function med noget with(this)... ? ved I noget om det måske er vejen?

mclemens -> jeg er ikke interesseret i at kalde en metode med nogle argumenter... det kræver for meget indsigt og er ikke indkapslet nok ;-)

roenving-> du har nogle gode konsistente regler, dem er jeg glad for at lære *S* Tak..

Well... men anyway, håber I kan se opgaven?
Avatar billede softspot Forsker
23. august 2006 - 23:17 #14
Jeg kan ikke lige se en løsning på hvordan du skal få den til at fungere, hvis du vil være i stand til at tildele værdier til attributterne efter din constructor er kørt - faktisk kan jeg heller ikke lige gennemskue, hvordan du skal få den multiply-funktion til at køre på de attributter med simple numeriske typer (jeg har i det mindste ikke haft held med at definere funktionelle funktioner på foobar-attributten).

Jeg kan dog se en løsning som dog bliver lidt mere omstændig end den du umiddelbart er ude efter og den ser således ud:


function Num(value) {
  this.value = (!isNaN(value) ? value : 0);
}

Num.prototype.multiply = function() {
  return this.value * 2;
}

function foo() {
  this.foobar = new Num(0);
  this.widget = new Num(0);
}

// initier objekt, tildel værdi og beregn
var f = new foo();
f.foobar.value = 15;
f.widget.value = 45;
f.foobar.multiply();
f.widget.multiply();

Det er muligt du kan bruger det indbyggede Number-objekt og så definere en prototype-funktion på dette som hedder multiply, men det synes jeg heller ikke jeg havde succes med. Der er givetvis andre som er mere erfarne udi JS og kan give dig en forkromet løsning... det var mit umiddelbare bud.
Avatar billede mclemens Nybegynder
23. august 2006 - 23:30 #15
Han kan 'ski' noget ham softspot :o)
Jeg kiggede på den og droppede det helt :D
Lige en lille rettelse:

Num.prototype.multiply = function() {
  return this.value * 2;
}

->

Num.prototype.multiply = function() {
  this.value*=2;
}
Avatar billede mclemens Nybegynder
23. august 2006 - 23:36 #16
Hov, nej min fejl - det er jo kun hvis værdien af widget eller foobar skal rettes
(sad og alert'ede f.widget.value istedet for f.widget.multiply()) ... Undskyld - og igen FEDT!
Avatar billede janus_007 Nybegynder
24. august 2006 - 01:12 #17
Det ser sq lidt snedigt ud det der.... Jeg lader den lige stå til og med torsdag, det kan være der kommer flere guldkorn ;-)

Jeg fandt det her:
<HTML>
<HEAD>
<TITLE>Estate Agent 2</TITLE>
<SCRIPT>
function House(name,rooms,price,garage) {
this.name=name;
this.rooms=rooms;
this.price=price;
this.garage=garage;
this.view=view;
}
function view() {
with (this) document.write(name+' has '+rooms+' rooms, '+(garage?'a':'no')+' garage, and costs £'+price+'<BR>');
}
house1=new House('House 1',4,100000,false);
house2=new House('Big House',5,200000,true);
house1.view();
house2.view();
</SCRIPT>
</HEAD>
</HTML>

(kilde:http://www.webdevelopersjournal.com/articles/jsintro3/js_begin3.html)

Det viser lidt med det with-keyword, kan I se om det umiddelbart kan bruges i mit tilfælde?
Avatar billede roenving Novice
24. august 2006 - 01:35 #18
with bruges til at målrette variabel-søgning, så det kunne også se sådan ud:

document.write(this.name+' has '+this.rooms+' rooms, '+(this.garage?'a':'no')+' garage, and costs £'+this.price+'<BR>');

-- men jeg tror ikke, du kommer udenom at sørge for at hver enkelt variabel er 'prototypet' !-)
Avatar billede mclemens Nybegynder
24. august 2006 - 01:41 #19
Legede lige lidt ...


<script type="text/javascript">

function Num(value) {
  this.value = (!isNaN(value) ? value : 0);
}

Num.prototype.multiply = function(f) {
  if(f==1)this.value*=2;
  else return this.value * 2;
}

function foo() {
  this.foobar = new Num(0);
}

foo.prototype.add = function(e,v) {
  this[e]=new Num(v);
}

// initier objekt, tildel værdi og beregn
var f = new foo();

f.foobar.value = 15;

alert(f.foobar.multiply()); /* Funktion uden variabel der skal returnere den dobbelte værdi af foobar */

alert(f.foobar.value); /* Tester foobar værdi - skulle ikke være ændret */

f.foobar.multiply(1); /* Funktion med værdi 1 - sætter værdien af foobar til det dobbelte istedet */

alert(f.foobar.value); /* Nu er værdien i foobar skiftet */


/* ... */
/* ... */
/* ... */

f.add('widget',100);
alert(f.widget.value);

</script>
Avatar billede mclemens Nybegynder
24. august 2006 - 01:42 #20
((( en mindre udvidelse af softspots :o) )))
Avatar billede mclemens Nybegynder
24. august 2006 - 01:47 #21
((( tilføjet denne funktion:
foo.prototype.add = function(e,v) {
  this[e]=new Num(v); /* den opretter en variabel på foo / f objectet efter contructoren er køre ... this[e] kan ikke skrives som this.e i dette tilfælde */
} )))
Avatar billede softspot Forsker
24. august 2006 - 08:20 #22
...og hvis den bliver defineret således:

foo.prototype.add = function(e,v) {
  this[e]=new Num((!isNaN(v) ? v : 0));
}

så kan den også kaldes uden den anden parameter, i hvilket tilfælde den så vil få standardværdien 0. Altså

f.add('widget');

Mht. aflæsning af variablerne, kan man definere en toString-funktion på Num-objektet (og måske endda en valueOf-funktion), som returnerer værdien af objektet, så slipper man for at kalde med f.widget.value, når variablen skal udskrives. Det kunne se således ud:

// metoden som kaldes, hvis objektet benyttes ifm. operationer der vedrører
// aflæsning, f.eks. alert(obj)
Num.prototype.toString = function() {
  return this.value;
}

// metoden som kaldes, hvis objektet benyttes ifm. operationer på primitive typer,
// så som addition, substraktion osv.
// Vær opmærksom på at at valueOf også bliver kaldt i dette tilfælde:
// alert("widget = " + obj);
// da der er tale om en addition...
Num.prototype.valueOf = function() {
  return this.value;
}

og værdien kunne så aflæses således:

alert(f.widget);

i stedet for

alert(f.widget.value);

Den sidste version vil stadig fungere, men metoden uden eksplicit angivelse af value-attributten virker bare lidt mere naturlig. Man SKAL stadig benytte value-attributten ved tildeling. Altså som hidtil:

f.widget.value = 20;
Avatar billede softspot Forsker
24. august 2006 - 08:23 #23
OK, min udvidelse af add-metoden var nok overkill, da det check jo alledere (og mere naturligt) bliver lavet i Num-objektets constructor... sorry.
Avatar billede janus_007 Nybegynder
25. august 2006 - 00:34 #24
Jeg siger tak til alle... rart med lidt eksperthjælp. Smid nogle svar, så fordeler jeg lidt point ;-)
Avatar billede softspot Forsker
25. august 2006 - 07:54 #25
Velbekomme :)
Avatar billede mclemens Nybegynder
25. august 2006 - 09:41 #26
Jeg har ikke rigtig bidraget med andet end en
lille funktion jeg lagde ind i softspot's (add)
og så lidt "spam" i trådem - så det er nok
en meget, meget, meget lille bid :o)

... (((synes at det var softspot's 23/08-2006 23:17:23, der fik det hele til at køre))) ...
Avatar billede softspot Forsker
25. august 2006 - 17:15 #27
Jamen, jeg takker for point - og hvis roenving også vil have en del af kagen må han jo lige sige til, så lægger jeg lige en lille kage... (hmmmm... der er et eller andet galt med den sætning...?? ;-)).
Avatar billede mclemens Nybegynder
25. august 2006 - 17:29 #28
Takker også for point :o)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Vi tilbyder markedets bedste kurser inden for webudvikling

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester