在JavaScript中实现实例成员/方法 [英] Implementing instance members/methods in JavaScript

查看:98
本文介绍了在JavaScript中实现实例成员/方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个问题源于我试图解决的有关在JavaScript中具有私有"实例变量的功能的问题.在提出我的问题之前,您可能需要阅读.

This question stems from a problem I was trying to solve regarding the ability to have "private" instance variables in JavaScript. You may want to read this, prior to my question.

为了完整起见,在提出问题之前,我已经说明了我的整个问题.我希望这将提供一个完整的示例,说明如何在JavaScript中正确地实现实例成员和方法,并且对于任何来这里的开发人员来说,都是要了解各种实现的陷阱.

For the sake of completeness, I have illustrated my entire problem, before asking the question. My hope is that this will provide a complete example of how to implement instance members and methods correctly in JavaScript, and for any developer who lands here, to understand the pitfalls of the various implementations.

考虑以下JavaScript对象:

Consider the following JavaScript object:

var MessageBox = (function() {
    function MessageBox(message) {
        this.message = message;
    }

    MessageBox.prototype.Show = function() {
        alert(this.message);
    }
})();

此对象是使用TypeScript建模的,可以按以下方式使用:

This object was modelled using TypeScript, and can be used as follows:

var msg1 = new MessageBox("Hello World");
msg1.Show(); // alerts "Hello World"

var msg2 = new MessageBox("Bye World");
msg2.Show(); // alerts "Bye World"

但我仍然可以拨打电话:

But I can still call:

msg1.message; // "Hello World"
msg2.message; // "Bye World"

很显然,this.message不是私有的.

现在考虑以下JavaScript对象:

Now consider the following JavaScript object:

var MessageBox = (function() {
    return function MessageBox(message) {
        var message = message;

        MessageBox.prototype.Show = function() {
            alert(message);
        }
    }
})();

这只是基于TypeScript的MessageBox对象的修改版本.

This is just a modified version of the TypeScript based MessageBox object.

var msg1 = new MessageBox("Hello World");
msg1.Show(); // alerts "Hello World"

var msg2 = new MessageBox("Bye World");
msg2.Show(); // alerts "Bye World"

但是等等...我要把扳手扔进去!

but wait...I'm about to throw a spanner in the works!

var msg1 = new MessageBox("Hello World");
var msg2 = new MessageBox("Bye World");
msg2.Show(); // alerts "Bye World"
msg1.Show(); // alerts "Bye World" ... wait, what!?

msg1.message // undefined
msg2.message // undefined

因此,我无法再访问message变量,但是现在,每个新实例都将覆盖最后一个实例消息.

So I can no longer gain access to the message variable, but now, every new instance overwrites the last instances message.

与我同在,这是要考虑的最后一个JavaScript对象:

Bear with me, this is the last JavaScript object to consider:

var MessageBox = (function() {
    return function MessageBox(message) {
        var message = message;

        this.Show = function() {
            alert(message);
        }
    }
}();

上面的对象不再在原型上实现Show(),所以现在我可以:

The above object no longer implements Show() on the prototype, so now I can:

var msg1 = new MessageBox("Hello World");
var msg2 = new MessageBox("Bye World");
msg2.Show(); // alerts "Bye World"
msg1.Show(); // alerts "Hello World"

msg1.message // undefined
msg2.message // undefined

太好了!现在我有了私有变量,它们不会互相覆盖!

Great! Now I have private variables, and they don't overwrite each other!

所以,最后一个问题是:之间有什么区别

So, finally the question: What is the difference between:

MessageBox.prototype.Show = function() {
}

this.Show = function() {
}

推荐答案

您最终遇到的问题有一个简单的答案:在原型上设置函数意味着可以从任何实例调用该函数,而在实例意味着只能从该实例调用它.两种方法都可以访问实例上的属性,但是您发现复杂的是,函数只能在声明它的作用域或包含作用域的范围内访问局部变量.

The question that you eventually get to has a simple answer: setting the function on the prototype means it can get called from any instance, while setting the function on the instance means it can be called only from that instance. Either way can access properties on the instance, but the thing that you're finding complicated is that either way the function only has access to local variables in the scope where it was declared or in containing scopes.

以下是想到的同时提供私有实例变量和私有原型变量的第一种方法.

The following is the first way that came to mind to provide both private instance and private prototype variables.:

var MessageBox = (function() {
    var privateProtoVar = "Hello";

    function MessageBox(message) {
        var privateInstanceVar = message;

        this.instanceMethod = function() {
            alert(privateInstanceVar); // Can access private instance var
            alert(privateProtoVar);    // Can access private prototype var
        }
    }        
    MessageBox.prototype.Show = function() {
        alert(privateProtoVar); // Can access private proto var
        // but can't access privateInstanceVar
    }    
    return MessageBox;
})();

var msg1 = new MessageBox("1"),
    msg2 = new MessageBox("2");

msg1.instanceMethod();  // "1", "Hello"
msg2.instanceMethod();  // "2", "Hello"
msg1.Show();            // "Hello"
msg2.Show();            // "Hello"

在内部MessageBox()函数中的内部中声明的任何函数都可以访问变量privateInstanceVar,但不能从prototype上的函数访问该变量,除非在同一范围内声明了这些变量(请勿在上面的示例中进行操作.)

The variable privateInstanceVar is accessible by any function declared inside the inner MessageBox() function, but not from functions on the prototype unless they're declared within that same scope (which I don't do in the above example).

如果您向实例稍后添加其他方法,即在上述结构之外,则这些方法 not 不能访问私有var,因为它们是在不同的范围:

If you add additional methods to instances later, i.e., outside the above structure then those methods do not have access to the private var because they're declared in a different scope:

msg1.newMethod = function() {
   alert(privateInstanceVar);
}
msg1.newMethod(); // error

演示: http://jsfiddle.net/SSEga/

这篇关于在JavaScript中实现实例成员/方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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