使javascript私有方法可以访问它的公共方法 [英] Making javascript private methods accessible to it's public methods

查看:74
本文介绍了使javascript私有方法可以访问它的公共方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

这里从公共方法(drawOrAdd)我无法访问私有方法(_convertArrayToTable),我该怎么做?

I understand there are couple of patterns to make javascript 'class-like'.
I would like to take the 'extending by prototype' way... simply bcoz it looks more neat. I am not worried about performance much here...
In the below example i have a class(basically function) MetricsChart, i have couple of public methods and one private method(basically a reusable method)
Here from the public method(drawOrAdd) i can't access the private method(_convertArrayToTable), how can i do that?

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类本身内... ...它对我有用:),我可以访问外面的公共方法,公共方法可以访问私有方法(服务于目的)。
以下代码...... 这是对的吗?我有什么事吗?

One way i accidentally found was to enclose the public methods inside the MetricsChart class itself...
It works for me :), i can access the public methods outside and the public method can access the private method (serves the purpose). Below code... It Is this right? Am i doing anything worng?

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 () {
    }

}


推荐答案

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

So, here a couple of things, in order to understand what you have done precisely. First of all:

function foo() {
    var i = 0;

    function bar() {
        return true;
    }
}

这里发生了什么:每次函数<$ c调用$ c> foo ,它在其范围内创建一个新变量 i ,以及一个新函数 bar 。函数 bar 和变量 i 在其范围内,这意味着它们是本地:使用此代码,无法访问 i bar outside 函数 foo 。还因为,一旦函数 foo 被终止, i bar 被处置。

What's happening here: every time the function foo is called, it creates in its scope a new variable i, and a new function bar. The function bar and the variable i are in its scope, it means they're local: there is no way, with this code, to access to either i or bar outside the function foo. Also because, once the function foo is terminated, both i and bar are disposed.

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

So, this is why you cannot access from your "public" method to the "private" one, and I hope it's more clear now. The only way for a function to access to a function or variable is that there is a reference shared in the same scope. So, this is what you have done in your last example: you define your "public" methods in the same scope where you define your "private" method. In this way they can access each other. However, the way you have done, has a big downside. As I said previously, the function bar is created every time the function foo is called. In a "class" example, it means:

function MyClass() {
    function myprivate() {}

    MyClass.prototype.mypublic = function () { return myprivate() }
}

这意味着每次你创建 MyClass 的实例时,你都会创建两个新函数,并且你一直在重写你的班级的原型。这远不是一个好方法。事实上,如果你有类似的东西:

It means that every time you're creating an instance of MyClass, you're creating two new functions, and you're rewrite all the time the prototype of your "class". This is far from be a good approach. In fact, if you have something like:

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!

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

So, you guess right but you executed wrong. What you need here is a the "module pattern": nowadays you can use CommonJS module in nodejs or AMD in browser and so on, but the basic idea is defined a "scope" and exports from this scope only what you want. In your case, you could have:

// 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

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

And that's it. You have created a closure, using the "module pattern", and from the "public" method you can access to the "private" function, because they're defined in the same scope. But because you do not do that in the "class" constructor, you don't redefine them every time you instantiate a new object. Therefore, the previous example written in this way, will give the right result:

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

console.log(_mypublic === b.mypublic) // true
console.log(_mypublic === a.mypublic) // true

这篇关于使javascript私有方法可以访问它的公共方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆