Javascript JS类,无需不断引用;这";供会员使用

Javascript JS类,无需不断引用;这";供会员使用,javascript,class,oop,this,Javascript,Class,Oop,This,我的典型JS类结构如下所示: MyClass = function(args) { this.myProp1 = undefined; this.myProp2 = args[0]; //...more member data this.foo = function() { return this.myProp1 + this.myProp2; //<- the problem. } //...more member functi

我的典型JS类结构如下所示:

MyClass = function(args)
{
   this.myProp1 = undefined;
   this.myProp2 = args[0];
   //...more member data 

   this.foo = function()
   {
       return this.myProp1 + this.myProp2; //<- the problem.
   }
   //...more member functions
}

//if MyClass extends a superclass, add the following...
MyClass.prototype = Object.create(MySuperClass.prototype);
MyClass.prototype.constructor = MyClass;
MyClass=函数(args)
{
this.myProp1=未定义;
this.myProp2=args[0];
//…更多成员数据
this.foo=函数()
{

返回this.myProp1+this.myProp2;//有一个关键字部分满足了您的要求:但强烈建议不要使用它,因为在某些情况下它是不明确的

如果访问不存在的成员,它将返回到
窗口
对象。 因此,您可以做的是声明稍后要使用的所有属性,然后使用
语句声明一个

如果我有你的选择,我可能会改变主意跳过
这个
,或者如果你可以,使用另一种语言

在其他几种语言中,例如C#和Java,当成员函数处理同一类/实例中的成员数据时,可以安全地忽略这一点。(我意识到JS的结构根本不同,因为它被设计为原型语言,而不是层次继承语言。)

这与继承链无关,继承链在js中也是静态的,而是js是一种动态语言,全局范围可以随意添加新变量,对象可以用任意属性修改

因此,不可能让标识符动态解析为局部变量或对象属性,我们希望通过使用属性访问器进行属性访问来明确区分它们

有没有办法使未指定的作用域不指向窗口,而是指向该窗口的当前本地值

“未指定范围”是静态确定和优化的局部范围。要使其指向对象(如果找不到属性,则返回变量),可以使用。但是,由于这种模糊性,它不仅速度慢,而且被认为是不好的做法-非局部代码可能会影响(变量的)查找(与实例交互)这会破坏封装,并且是一个可维护性问题

我典型的JS类结构


当然,您也可以更改这一点,并使用通过闭包访问的局部变量作为成员(另请参见)。这解决了
This
的问题,但也很快(尽管可能比
This
更快).

我不确定是语言限制还是其他原因,但您用于创建类和成员函数的模式无助于实现您想要的目标

为什么不试试这样的模块模式呢

CalcModule=(函数(){
var add=函数(a,b){
返回a+b;
};
var sub=功能(a,b){
返回a-b;
};
var_privateColution=函数(){
};
返回{
“添加”:添加,
“sub”:sub
};
});
在这里,您可以通过在返回对象中不包含私有成员来获得一个模拟私有成员的控件

更新:我不确定模块模式类的扩展


更新:为函数声明添加了var

在这里为后代添加我自己的答案,因为在某个阶段,如果我被迫(1)预先编写
和(2)使用可怕的
,那么有一个(3)rd解决方案可能会很有用

假设我们不直接访问任何成员数据,而是为每个数据属性使用getter和setter方法

在这种情况下,可以使用Doug Crockford讨论的私有概念:

MyClass = function()
{
   var prop = undefined;
   this.getProp() {return prop;}
   this.setProp(value) {prop = value;}

   //now in standard, non-getter and -setter methods, we can do...
   this.foo = function()
   {
       return prop + prop; //<- no problem: no more 'this'
   }
}
MyClass=function()
{
var prop=未定义;
this.getProp(){return prop;}
this.setProp(value){prop=value;}
//现在在标准的非getter和setter方法中,我们可以。。。
this.foo=函数()
{

return prop+prop;//可能最好避免使用
with
语句,因为
with
语句会禁用优化。此外,
with
语句不能在严格模式下使用。请参阅ECMA 262§12.10.1:“严格模式代码可能不包括WithStatement。在此上下文中出现WithStatement将被视为语法错误。”

一个选项是使用扩展到属性访问的语法扩展。例如,在0.3.2中,
@property
被添加为
此.property
的缩写

如果不想使用CoffeeScript,可以使用创建自己的宏。下面是添加
@property
速记功能的宏示例:

macro @ {
    case { _ $x:ident } => { return #{ this.$x }; }
    case { _ $x } => { return #{ this[$x] }; }
}

function Person(name) {
    @name = name;
}

var person = new Person("Johnny Appleseed");
alert(person.name);
sweet.js编译器,
sjs
,生成:

function Person$630(name$632) {
    this.name = name$632;
}
var person$631 = new Person$630('Johnny Appleseed');
alert(person$631.name);

您可以将
一起使用,但这真的很难看。或者,您可以将属性存储在本地作用域中,而不是将其分配给
。您好@RobW,是的,缓存为本地变量是我通常做的事情,但在复杂的应用程序中可能会很快变得繁重。此外,我从ActionScript中知道
一起使用,但我当时的理解是,它可能非常慢。也许我应该看看它在现代JS engines.FWIW下的表现,在规范中要深入研究的关键词是对象环境记录:为什么要在构造函数中定义foo,而不是在它的原型上定义foo?按原样编写的代码似乎并不需要每个实例在你的回答中,你提到了模块模式和Douglass。我不太喜欢他关于构造函数的想法,还没有看到他做“经典继承”的演示或文章"正确。他没有修复错误的代码,而是将其归咎于JS。模块模式不允许您拥有访问私有变量的特权函数,因此无法将它们放在原型上。在这个答案的末尾是一个指向可用于模拟受保护的模式的链接。但仍然无法解决您的
这个
问题为什么?
function Person$630(name$632) {
    this.name = name$632;
}
var person$631 = new Person$630('Johnny Appleseed');
alert(person$631.name);