简体   繁体   中英

can prototype functions access local variables?

I thought that functions created using .prototype were supposed to be able to access local variables. Here is what I'm talking about:

function obj() {
    var a = "String";

    this.innerPrint = function() {
        document.write("<p>" + a + "</p>");
    };
}

obj.prototype.outerPrint = function() {
    document.write("<p>" + a + "</p>");
};

var inst = new obj();
inst.innerPrint();
inst.outerPrint();

What I thought would happen is that both of these functions would do the same thing. But what actually happened is outerPrint doesn't have access to the variable a. Could someone explain to me how you get locals in a prototype function.

Here is a fiddle running this code: http://jsfiddle.net/Wryte/mxXzg/

By the way, I want to use prototype functions because then each instantiation of the object doesn't have a copy of the function but they each point to the same one.

If you want your variable a to be still accessible after the constructor has finished execution, change your code to

function obj() {
    this.a = "String";

    this.innerPrint = function() {
        document.write("<p>" + this.a + "</p>");
    };
}

obj.prototype.outerPrint = function() {
    document.write("<p>" + this.a + "</p>");
};

Or define a getter if you don't want to provide direct write access :

function obj() {
    var a = "String";
    this.getA = function() {
        return a;
    }
    this.innerPrint = function() {
        document.write("<p>" + a + "</p>");
    };
}

obj.prototype.outerPrint = function() {
    document.write("<p>" + this.getA() + "</p>");
};

When you declare 'a' it's declared in the lexical scope of the obj()-function. All instance variables needs to be prototype'd as well, so insted of var a it should be declared as this.a .

Of course not, you cannot access one function's locals from another function defined outside the first . It does not matter if the second is defined in the prototype property of the first. Each invocation of your obj function defines a new local a variable, so you cannot avoid having separate copies of the function that needs to access it.

I assume you actually require that variable to be a local and not an instance property, so one possible approach would be to have only a thin local wrapper around your function:

function obj() {
    var a = "String";

    this.wrapper = function() { outerPrint.call(this, a); }
    this.innerPrint = function() {
        document.write("<p>" + a + "</p>");
    };
}

function outerPrint(a) {
    document.write("<p>" + a + "</p>");
};

Again, I assume you have a more complex function in place of outerPrint , so this way you can avoid the duplication of a large function at the expense of duplication of a minimal wrapper. This way you retain the privateness of the a variable, while a public getter would allow external code to inspect its value.

UPDATE: On @Bergi's remark, I've modified the code to make outerPrint a local function in the same scope where the obj constructor is defined. No longer being on the prototype, it will not be directly callable for obj instances. Note that all of the code will need to be inside a function scope, in order to avoid a global outerPrint function.

No, it is a local variable. Scope rules are not bypassed because of a property named prototype .

The variable is accessible only from functions defined inside the constructor; they are called privileged because of that. Of course, when those are accessible as public methods you can call them from outside, ie.

Obj.prototype.outerPrint = function() {
    this.innerPrint();
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM