使javascript私有方法可以访问它的公共方法

时间:2013-10-17 06:40:43

标签: javascript prototype

我知道有几种模式可以使javascript'类似'。“ 我想采取'原型扩展'的方式...简单地说它看起来更整洁。我在这里并不担心性能......
在下面的例子中我有一个类(基本上是函数) MetricsChart ,我有几个公共方法和一个私有方法(基本上是可重用的)法)
这里从公共方法(drawOrAdd)我无法访问私有方法(_convertArrayToTable),我该怎么做?

function MetricsChart(containerId, chartType) {
    this._container = document.getElementById(containerId);
    this._chartType = chartType;
    this._isChartDrawn = false;
    this._chartData = null;

    var _convertArrayToTable = function (data) {
        return google.visualization.arrayToDataTable(data);
    }
}

MetricsChart.prototype.drawOrAdd = function(data)
{
    if (!this.isChartDrawn()) {
        var chart = new google.visualization.LineChart(this._container);
        if (chart) {
            var table = _convertArrayToTable(data);
            console.log(table);
            this._isChartDrawn = true;
        }
    }
}

MetricsChart.prototype.isChartDrawn = function () {
    return this._isChartDrawn;
}

MetricsChart.prototype.getChartData = function () {
}

我意外发现的一种方法是将公共方法包含在MetricsChart类本身内... ...它适用于我:),我可以访问外部的公共方法,公共方法可以访问私有方法(达到目的)。 代码下面...... 这是对的吗?我有什么事吗?

function MetricsChart(containerId, chartType) {
    this._container = document.getElementById(containerId);
    this._chartType = chartType;
    this._isChartDrawn = false;
    this._chartData = null;

    var _convertArrayToTable = function (data) {
        return google.visualization.arrayToDataTable(data);
    }

    MetricsChart.prototype.drawOrAdd = function (data) {
        if (!this.isChartDrawn()) {
            var chart = new google.visualization.LineChart(this._container);
            if (chart) {
                var table = _convertArrayToTable(data);
                console.log(table);
                this._isChartDrawn = true;
            }
        }
    }

    MetricsChart.prototype.isChartDrawn = function () {
        return this._isChartDrawn;
    }

    MetricsChart.prototype.getChartData = function () {
    }

}

4 个答案:

答案 0 :(得分:4)

所以,这里有几件事,以便了解你所做的事情。 首先:

function foo() {
    var i = 0;

    function bar() {
        return true;
    }
}

这里发生了什么:每次调用函数foo时,它会在其范围内创建一个新变量i和一个新函数bar。函数bar和变量i在其范围内,这意味着它们是本地:使用此代码无法访问{{1} }}或i 之外的函数bar。另外,因为一旦函数foo被终止,fooi都会被处理掉。

所以,这就是为什么你不能从你的“公共”方法访问“私人”方法,我希望现在更清楚。函数访问函数或变量的唯一方法是在同一范围内共享引用。因此,这就是您在上一个示例中所做的事情:您在定义“私有”方法的同一范围内定义“公共”方法。通过这种方式,他们可以互相访问。但是,你做的方式有很大的缺点。正如我之前所说,每次调用函数bar时,函数bar都是创建的。在“类”示例中,它表示:

foo

这意味着每次创建function MyClass() { function myprivate() {} MyClass.prototype.mypublic = function () { return myprivate() } } 的实例时,您都会创建两个新函数,并且您一直在重写“类”的原型。这远不是一个好方法。事实上,如果你有类似的东西:

MyClass

所以,你猜对了,但你做错了。你需要的是“模块模式”:现在你可以在nodejs中使用CommonJS模块或者在浏览器中使用AMD等等,但是基本思想被定义为“范围”并且只从你想要的范围导出。在您的情况下,您可以:

var a = new MyClass();
var _mypublic = a.mypublic;
var b = new MyClass();

console.log(_mypublic === b.mypublic) // false
console.log(_mypublic === a.mypublic) // false too!

就是这样。您已使用“模块模式”创建了一个闭包,并且您可以从“public”方法访问“私有”函数,因为它们是在同一范围内定义的。但是因为你没有在“类”构造函数中这样做,所以每次实例化一个新对象时都不会重新定义它们。因此,以这种方式编写的前一个示例将给出正确的结果:

// this is your "module"
;(function(exports) {
    // your local (private) function
    var _convertArrayToTable = function (data) {
        return google.visualization.arrayToDataTable(data);
    }

    function MetricsChart(containerId, chartType) {
        this._container = document.getElementById(containerId);
        this._chartType = chartType;
        this._isChartDrawn = false;
        this._chartData = null;
    }

    MetricsChart.prototype.drawOrAdd = function(data) {
        if (!this.isChartDrawn()) {
            var chart = new google.visualization.LineChart(this._container);

            if (chart) {
                var table = _convertArrayToTable(data);
                console.log(table);
                this._isChartDrawn = true;
            }
        }
    }

    // you decided to exports to the main scope what you want
    exports.MetricsChart = MetricsChart;

}(this)); // here `this` is the global object

答案 1 :(得分:0)

要访问私有方法,请使用权限方法。请查看此文档:http://javascript.crockford.com/private.html

关于您的代码检查此答案: Setting javascript prototype function within object class declaration

P.S。

    function Test()
    {
        var p = function(pv)
        {
            //
        }

        this.e = function (ap) { p(ap) }
    }
    var n = new Test();
    n.e("e"); // It is legal call
    n.p();    // will throw

但是如果你在c-tor中声明一个私有函数,它将在第一次创建这种类型的对象时执行。在原型中声明方法时,在任何代码执行之前添加此方法。通常,浏览器首先检查js文件以收集原型的所有方法,然后执行任何代码。因此,当您将原型方法声明为c-tor时,此方法仅在首次创建这些类型的对象后才可用。 (抱歉我的英文)。

检查这种情况:

        function Test()
    {
        alert(this.ST_A);//alert undefined
        alert(this.ST_B);//alert 2
        Test.prototype.ST_A = 1;
        alert( this.ST_A)//alert 1
    }
    Test.prototype.ST_B = 2;

在第一次通过时,浏览器将使用ST_B填充Test,并且随时可以在任何地方使用ST_B。在第二次传递之后,浏览器将开始执行代码,此时ST_A将不可见,直到浏览器执行Test.prototype.ST_A = 1;

答案 2 :(得分:0)

你所做的并不是必然的错误" ......它看起来很奇怪。此外,您无法访问" MetricsChart.prototype。*"直到你创建了" MetricsChart"的实例。根据您使用此对象的方式,可能无关紧要。

话虽这么说,另一种方法是保留原始结构,但在构造函数之外移动以下内容:

var _convertArrayToTable = function (data) {
    return google.visualization.arrayToDataTable(data);
}

你的模块仍然是私有的,应该足够好(你正在使用模块吗?)。

答案 3 :(得分:0)

你做得很好。

在覆盖或直接访问它们方面,您不能以任何OOP语言继承私有方法。他们是私人的。因此将它们原型化为继承目的是没有意义的。你已经将它们包装在功能范围内,因此它们就像它们需要的那样“私密”。