开发者

What's going on in the background with regard to this JavaScript?

I was reviewing some today, when I encountered the following convention :

TestParam(1);

function TestParam(p){
    var p = p + 1;
    alert(p);   // alerts '2'
}

Now, obviously, the developer didn't mean to delcare 'p' within the function, instead maybe meaning:

    p = p + 1;

But the code still worked, i.e. the value alerted was "2". So it got me to thinking. What would happen in the following scenario:

var a = 1;
TestParam(a);
alert(a);  // alerts "1"

function TestParam(p){
    var p = p + 1;
    alert(p);   // alerts '2'
}

Again the alerts were as I suspec开发者_Go百科ted (as intimated in the comments above). So then I was curious as to what would happen if I used an object:

var a = { b: 1 };
TestParam(a);
alert(a.b);  //alerts 1

function TestParam(p) {
    var p = {b:p.b + 1};
    alert(p.b); //alerts 2
}

So, in this instance, JavaScript has 'remembered' the variable a, even though when it is passed to TestParam as p, p is redeclared.

Now if I were to have done the following within the function, then both alerts would have been "2"

    p.b++;
    //var p = {b:p.b + 1};

I.e. it would have modified the member b of the original object. I get this. Its the previous scenario that baffles me!

I realise this is quite a hypothetical question that is unlikely to carry much real-world usefulness, but it still made me quite curious, as to what is going on in the background, and how exactly JavaScript is scoping and referencing these variables.

Any thoughts?


Variables are scoped to the enclosing function in JavaScript. And you can declare them as many times as you like.

Objects are not tied to variables; many variables can refer to the same object. (This is sometimes called aliasing.) This is what's happening in your last example. JavaScript has not "remembered" the variable a at all; rather, p and a refer to the same object, so when it is changed via p, you can see those changes via a.

Here's an example that might make more sense to you. Sometimes a person has more than one identity.

var Clark = new Person;
var Superman = Clark;  // Maybe not everybody needs to know these two are
                       // the same person, but they are.
Clark.eyes = "brown";
alert(Superman.eyes);  // should be brown, right?

Knowing the rules of the language you're using has tremendous "real-world usefulness". Not understanding these two rules is the source of a lot of confusion and bugs.


Javascript generally passes all arguments to functions by reference except when the argument is a number or a string. Javascript passes numbers and strings by value which is why your first example works the way it does.


I believe there's a typo in your code. I think you mean:

function TestParam(p) {
    var p = {b:p.b + 1}; // p.b, not p.a (p.a == undefined)
    alert(p.b);
}

In your example:

var a = { b: 1 }; // "a" is defined in the global scope
TestParam(a);
alert(a.b);  // alerts 1

function TestParam(p) {
    var p = {b:p.a + 1}; // "p" is defined in TestParam()'s scope
    /* But not until after the expression on the right side of the assignment
       has completed--that's why you can use p.a 
    alert(p.a); //alerts 2
}

At first, "p" is passed as a reference to the global variable "a", but then you redefine it in the first line. So, for example:

var a = { b: 1 };
alert(a.b); // Alerts 1
TestParam(a);
alert(a.b); // Alerts 2
TestParam(a);
alert(a.b); // Alerts 3

function TestParam(p) {
    p.b++;
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜