原型函数可以访问局部变量吗?

时间:2012-09-26 13:18:28

标签: javascript prototype

我认为使用.prototype创建的函数应该能够访问局部变量。这就是我在说的:

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();

我认为会发生这两种功能都会做同样的事情。但实际发生的是outerPrint无法访问变量a。有人可以向我解释如何在原型函数中获得本地人。

这是运行此代码的小提琴: http://jsfiddle.net/Wryte/mxXzg/

顺便说一下,我想使用原型函数,因为那时对象的每个实例都没有函数的副本,但它们都指向同一个函数。

4 个答案:

答案 0 :(得分:1)

如果您希望在构造函数执行完毕后仍可访问变量a,请将代码更改为

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

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

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

如果您不想提供直接写访问权限,请定义一个getter:

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>");
};

答案 1 :(得分:1)

当你声明'a'时,它是在obj() - 函数的词法范围内声明的。所有实例变量也需要原型化,因此var a的内容应该声明为this.a

答案 2 :(得分:0)

当然不是,你不能从第一个之外定义的另一个函数访问一个函数的本地。如果第二个是在第一个的prototype属性中定义的,则无关紧要。每次调用obj函数都会定义一个 new 本地a变量,因此您无法避免使用需要访问它的函数的单独副本。

我假设您实际上要求该变量是本地而不是实例属性,因此一种可能的方法是在您的函数周围只有一个瘦的本地包装器:

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>");
};

同样,我假设你有一个更复杂的函数来代替outerPrint,所以这样你就可以避免重复大型函数,但代价是重复最小的包装器。这样您就可以保留a变量的私有性,而公共getter则允许外部代码检查其值。

UPDATE:在@ Bergi的评论中,我修改了代码,使outerPrint在定义obj构造函数的同一范围内成为本地函数。不再是原型,它不能直接调用obj个实例。请注意,所有代码都需要在函数范围内,以避免全局outerPrint函数。

答案 3 :(得分:0)

不,它是本地变量。由于名为prototype的属性

,因此不会绕过范围规则

该变量只能从构造函数中定义的函数访问;因此,他们被称为特权。当然,当那些可以作为公共方法访问时,您可以从外部调用它们,即

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