JavaScript 中与 PHP 的 ::(作用域解析运算符)相当的操作符是什么?

6
在PHP中,你可以这样做:
class myClass() {
    function doSomething(someVar) {
         // do something here
    }
    // etc... (other methods and properties)
}

然后,当然,您可以在实例化该类之后调用该方法,就像这样:
$myObj = new myClass();
$myObj->doSomething();

但是您也可以选择将该方法作为独立函数调用,而不必实例化类(但在该函数中需要注意依赖项),如下所示:

myClass::doSomething();

我认为这是从C++借鉴过来的东西...在PHP代码中它被称为Scope Resolution Operator(Paamayim Nekudotayim)...
http://en.wikipedia.org/wiki/Scope_resolution_operator#PHP
http://www.php.net/manual/en/language.oop5.paamayim-nekudotayim.php

如何在JavaScript中实现这样的操作?这似乎不可能。
也许我正在错误地处理问题,我应该透露一下我想要实现什么...

我只需要一个像这样的函数:

function submitContactForm(form) {
    // pretty JavaScript...
}

我很满意它是一个函数。但我想实现一个“resetContactForm()”,但希望它以某种方式附加到submitConatctForm函数。

我知道我可能可以这样做:

var contactForm = {
   "submit" : function(form) {
       //...
   },
   "reset" : function(form) {
       //...
   }
}

我本来会像这样回答我的问题...

但是,除了我不喜欢这种语法并且想要避免它之外,还有一个事实,上面的结构不能用作类定义,它与PHP中的不同...所以回到最初的问题:是否有一种JavaScript结构可以同时用作类定义和独立函数集合?


3
那不是JSON语法,而是JavaScript对象语法,如果没有特殊字符,你不需要引号。在JavaScript中,Paamayim Nekudotayim没有用处,因为没有类,也没有静态方法。 - elclanrs
好的,引号不会有影响。无论如何还是谢谢你。我已经从我的帖子中删除了“JSON”。 - Rolf
1
JavaScript没有类,因此没有用于作用域解析的运算符。请按照链接中的建议在JavaScript中将方法附加到对象上。就像@Deepsy所说的那样。 - bishop
你只能使用::来表示静态函数和常量。你不能随意决定使用->或者::,你需要使用->来表示实例化对象的函数和常量,而使用::来表示类的静态函数和常量。 - chiliNUT
4个回答

3
你对原型继承的理解有误 - 实际上,你可以将第二个示例用作“类”定义,并且方法可以从“类”或“实例”中调用:
// This is a normal JavaScript object
// not JSON as another commenter pointed out.
var ContactForm = {
   submit: function(form) {
       form = form || this.form;
       // general contact form submission implementation
   },
   reset: function(form) {
       form = form || this.form;
       // general contact form reset implementation
   },
   setForm: function(form) {
       this.form = form;
   }
};

// Now we will create an instance of the contactForm "class"
// We are setting the prototype of `firstContactForm`
// to point at the `contactForm` object.
// If we wanted to we could create a function on the
// ContactForm object (e. g. `create`) that would invoke
// Object.create for us. (i. e. `ContactForm.create()`)
var firstContactForm = Object.create(ContactForm);
firstForm.setForm(document.getElementById("someForm"));
firstForm.reset();

 // But, we can also use the function as a "static":
 ContactForm.reset(document.getElementById("someForm"));

作为对你问题的另一部分的回答,如果你想让它成为可调用的“独立”内容,你也可以直接传递数据,就像我们在submitreset的示例中使用的form = form || this.form;检查一样。
或者,你可以使用callapply(正如 @elclanrs在他的回答中指出的那样),并始终使用this.form
 ContactForm.reset.call({form: document.getElementById("someForm")});

@elclanrs的解决方案很好,从“严格技术”角度来看可能更正确,但你的更接近我所想的,并且更容易理解... - Rolf

3
在JavaScript的对象语法中,如果没有特殊字符,就不需要加引号:
var obj = {
   key: function() {
     ...
   },
   ...
}

在JavaScript中,Paamayim Nekudotayim没有任何作用,因为没有类和静态方法。但是JavaScript有一个动态上下文,我们称之为 this。它与PHP或其他经典继承语言中的this没有任何相似之处,除了关键字的名称。

一个典型的JavaScript“类”如下所示:

// A "Class"
var Person = (function(){
  // Private stuff, shared across instances
  var instances = [];

  // The constructor AKA "__construct"
  function Person(name) {
    this.name = name;
    instances.push(this); // keep track of instances
  }

  // Static methods, attached to the constructor
  // don't need an instance
  Person.instances = function() {
    return instances;
  };

  // Public methods
  Person.prototype = {
    say: function() {
      return this.name +' says hello!';
    }
  };

  return Person;
}());

现在,你如何使用它:
var mike = new Person('Mike');
mike.say(); //=> Mike says hello!
Person.instances().length; //=> 1

到目前为止一切都很好。关于JavaScript中的"作用域分辨符",您可以显式地传递上下文;由于this是动态的,因此您可以借用Person的say方法并在任何其他上下文中调用它,例如:

Person.prototype.say.call({name:'John'}); //=> John says hello!

2
您可以像这样将其制作为一个类:
function ContactForm(form) {
    this.form = form;
}

ContactForm.prototype.submit = function() {
    console.log('submiting: ' + this.form);// do something with the form
}

ContactForm.prototype.reset = function() {
    console.log('reseting: ' + this.form);
}



var someForm = ...;

var form = new ContactForm(someForm);

form.submit();
form.reset();

或者如果您想静态使用它们,可以按照以下方式进行:

var ContactForm = (function() {
    var reset = function(form) {
        console.log('reseting' + form);
    };

    var submit = function(form) {
        console.log('submiting' + form);
    }

    return {
        submit: submit,
        reset: reset
    }
}()); // note that this is self-executing function

并像这样使用它

ContactForm.submit(form);
ContactForm.reset(form);

那么我将实例化一个对象,这正是我想避免的...因为我不想跟踪该实例,并且也不想创建多余的实例。好吧,也许我有点过度了,你的代码完全没问题(谢谢),从实用的角度来看,它可能是最好的答案。 - Rolf

1

阅读Sean Vieira和elclanrs的答案让我有了更好的理解。 我编写了这段代码作为概念证明,并确保我理解了我所读的内容。这本质上是elclanrs答案的简化版本:

function contactForm(form) {
    this.form = form;
}
contactForm.prototype.submit = function() {
    alert("submit "+this.form);
}
contactForm.prototype.reset = function() {
    alert("reset "+this.form);    
}

// Without instanciating:
contactForm.prototype.submit.call({form:'form2'});

// With instance:
myForm = new contactForm('form1');
myForm.reset();

看起来JavaScript中已经有这种“功能”,尽管形式不同,而且不太直接。

此外,Sean Vieira的方法已经完成:

var ContactForm = {
   submit: function(form) {
       form = form || this.form;
       alert("submit "+form);
   },
   reset: function(form) {
       form = form || this.form;
       alert("reset "+form);
   },
   createForm: function(form) {
       var myForm = Object.create(this);
       myForm.setForm(form);
       return(myForm);
   },
   setForm: function(form) {
       this.form = form;
   }
};

// instanciated
myContactForm = ContactForm.createForm('Me Form');
myContactForm.submit();

// no instance
ContactForm.submit("Some Form");

此外(我的贡献),如何使用包装函数呢?在我看来,这似乎是一个不错的选择。

function contactForm(form) {
    this.form = form;
    this.submit = function() {
        submitContactForm(this.form)
    }
    this.reset = function() {
        resetContactForm(this.form);
    }
}
function submitContactForm(form) {
    alert("submit "+form);
}
function resetContactForm(form) {
    alert("reset "+form);    
}

// Without instanciating:
submitContactForm('form2');

// With instance:
myForm = new contactForm('form1');
myForm.reset();

没有完美的解决方案...


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接