1

I can't get my javascript function to work.

if (!cHp) { cHp = 200 };

Works like a charm, but

function checkNull(x, y) {
if (!x) { x = y; }
}

Doesn't work at all.

What am I doing wrong?

ZheX
  • 23
  • 3

2 Answers2

7

It does work, but it doesn't do you any good because JavaScript is purely call-by-value. That means that in your function, the parameters "x" and "y" contain copies of the values present in the calling environment.

Thus,

checkNull(b, 2 + 17);

causes copies of the value of the variable "b" and the number 19 to be passed to the function. The function can do whatever it wants to "x" and "y", but that'll make no difference to the variable "b" in the calling context.

edit — OK to expand on this topic and cut off the over-long comment thread, let's talk about what "call-by-value" (and, for contrast, "call-by-reference") means. In a call-by-value parameter passing scheme, the values of actual parameters in the calling environment are copied into the parameter variables of a called function. In a call-by-reference scheme, a reference to some sort of variable in the calling environment is passed to the called function. How are those two different?

In a call-by-value scheme, this is what happens:

var a = 1;
function change(b) {
  b = 2;
}

change(a);
alert(a); // still 1

In a call-by-reference scheme, however, this is true:

// FANTASY CODE - NOT REAL JAVASCRIPT
var a = 1;
function change(b) {
  b = 2;
}

change(a);
alert(a); // it is 2 in this fantasy call-by-reference code

Note that one implication of a call-by-reference scheme is that the actual parameter in the calling environment must be a variable or an object property or something; that is, it must be what's called an "l-value" in programming language terms. Another way to say it is that it must be something that can appear on the left side of an assignment expression.

Things get a little confusing because of the way variables in JavaScript take on objects as their "value". When you assign an object to a variable:

var myObj = {};

you're really assigning a reference to the object. That's completely transparent in JavaScript and you don't really need to think about it. Juggling object values is as easy as primitive values in JavaScript. However, what it means is that when an object value is passed to a function, the fact that the actual value of the variable is a reference to the object means that the call-by-value semantics of JavaScript seem similar to a call-by-reference scheme:

var a = { property: 1 };
function change(b) {
  b.property = 2;
}

change(a);
alert(a.property); // it's 2!! OMG call-by-reference! (not)

Yes, it's possible for a function to modify the value of a property on an object passed as a parameter. Is that call-by-reference? No, it's not, at least not if you care about what the term "call-by-reference" means. Even though that function can change the value of the "property" property, it still cannot change the value of "a" itself! That's what call-by-reference means.

There are other parameter-passing schemes rarely seen nowadays. One that's kind-of fascinating is "call-by-name" from ALGOL 60. What that scheme did was to treat the actual parameter sort-of like an implicit function, such that in the called function a reference to the parameter would re-evaluate the parameter expression. There's also "call-by-value/result", which means that the actual parameter is passed by value, but when the function returns the then-current value of the parameter in the function is implicitly copied back to the source variable in the calling environment. (That scheme also requires the actual parameter to be an l-value, like call-by-reference.)

Pointy
  • 405,095
  • 59
  • 585
  • 614
  • That is true for primatives, but consider an Array or Object as examples, see my fiddles http://jsfiddle.net/Xotic750/pGcgy/ – Xotic750 Apr 24 '13 at 13:51
  • Thanks Pointy. What should I do do make it assign a to the variable i use an input then? – ZheX Apr 24 '13 at 13:54
  • 1
    @ZheX there's no way to do that in JavaScript. You can return a value from the function and explicitly make the (re-)assignment in the calling environment. – Pointy Apr 24 '13 at 13:57
  • Javascript is predominantly cal-by-reference, with the exception of strings and numbers - or primitives. – CBusBus Apr 24 '13 at 13:57
  • 1
    @Xotic750 arrays and objects are also passed by value; the "value" involved is the **reference** to the object. The term "call-by-reference" has a specific meaning when discussing programming language semantics, and the ability to modify objects via passed references is not that meaning. – Pointy Apr 24 '13 at 13:57
  • @SOliver that is not true at all. JavaScript is 100% purely call-by-value in absolutely all cases. – Pointy Apr 24 '13 at 13:58
  • @Pointy consider the following `a = {f:1};` `function shoe(param){param.f = "rocket"};` `console.log(a);` – CBusBus Apr 24 '13 at 14:00
  • @SOliver that is simply not what the term "call-by-reference" means. The value of the variable "param" is the **reference** to the object, and that value is what's passed to the function. Note that it remains impossible for the function to alter the value of the variable "param" in the **calling** environment; **that** is what's possible in a true call-by-reference language. – Pointy Apr 24 '13 at 14:01
  • It just seemed to me that a little more explanation was rquired for the OP so as not to become confused in the future, something like this perhaps? http://stackoverflow.com/a/6605700/592253 – Xotic750 Apr 24 '13 at 14:03
  • @Pointy I'm not sure what you're gettin' at here: I said that other than primitives, it's call-by-reference (using pointers). This is the case. What you mean (I think) is that you can't explicitly say "pass this as a reference" where a variable is a primitive. – CBusBus Apr 24 '13 at 14:06
  • @SOliver again, the terms "call-by-value" and "call-by-reference" have specific well-defined meanings in discussions of programming language semantics. What you're saying is true, but it doesn't have anything to do with the way JavaScript passes parameters. The key question is this: if you can write a function that, by modifying the value of a parameter (not a **property** of a parameter - the parameter itself), can modify a variable in the calling context, then you've got call-by-reference. If not, then you don't. – Pointy Apr 24 '13 at 14:08
  • @SOliver yes I've seen that blog post many times, and I don't agree with it; it misuses the terminology. C++ is a language that has (optional) call-by-reference. That's what `&foo` parameters are. JavaScript doesn't have that feature. – Pointy Apr 24 '13 at 14:09
  • @Pointy Ok, I'm with you on this one. I don't believe that call-by-value is entirely accurate either though since its description states that the variable outwith the scope of the function remains unchanged, which isn't true. – CBusBus Apr 24 '13 at 14:13
  • I am not arguing the semantics of discussion, I agree that I can not modify the property only the parameter. It was more about the wording "copy", as without such knowledge it will be confusing when your code doesn't do what you then expect, ie. mutating parameters within the function. Huh, that doesn't sound any clearer than your explanation to which I refer. But I hope you know what I mean. I will remove my comments shortly. – Xotic750 Apr 24 '13 at 14:28
  • @Xotic750 feel free to leave your comments - I've expanded the answer. I don't think these discussions hurt anything, and they may someday be useful to somebody. – Pointy Apr 24 '13 at 14:30
0

What you need to do is have the function return a value and assign the return to a variable. Try something like this:

var checkNull = function (x, y) {
        if (!x) {
            return y;
        }
        return x;
    },
    cHp,
    testVar;

cHp = checkNull(testVar, 200);  // will return 200 since testVar is undefined

testVar = 100;

cHp = checkNull(testVar, 200);  // will return 100 since testVar is defined
Derek Henderson
  • 9,388
  • 4
  • 42
  • 71