【问题标题】:Javascript equivalent of PHP's :: (Scope Resolution Operator)Javascript 等效于 PHP 的 ::(范围解析运算符)
【发布时间】:2014-01-24 06:11:24
【问题描述】:

在 PHP 中,你可以这样做:

class myClass() {
    function doSomething(someVar) {
         // do something here
    }
    // etc... (other methods and properties)
}

然后,当然,您可以在实例化类之后调用该方法,如下所示:

$myObj = new myClass();
$myObj->doSomething();

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

myClass::doSomething();

我相信这是为 C++ 借来的东西... 它被称为范围解析运算符(PHP 代码中的 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 结构同时用作类定义和独立函数的集合?

【问题讨论】:

  • 这不是 JSON 语法,它是 JavaScript 的对象语法,如果没有任何特殊字符,则不需要引号。 Paamayim Nekudotayim 在 JavaScript 中没有位置,因为没有类,没有静态方法。
  • 好吧,引号不会受到伤害。不管怎么说,还是要谢谢你。我已经从我的帖子中删除了“JSON”。
  • Javascript doesn't have classes 因此范围解析运算符没有用处。按照该链接中的建议将方法附加到 Javascript 中的对象。就像@Deepsy 刚刚说的那样。
  • 您只能将:: 用于静态函数和常量。您不仅可以选择使用-> 或::,还可以将-> 用于实例化对象的函数和常量,并将:: 用于类的静态函数和常量。

标签: javascript php class oop scope-resolution


【解决方案1】:

您误解了原型继承-实际上您可以将第二个示例用作“类”定义,并且可以从“类”或“实例”调用方法:

// 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"));

在回答您问题的另一部分时,如果您想让它成为可调用的“独立”,您还可以允许直接传入数据,就像我们在示例中使用 @ 987654323@ 签入submit 和reset。

或者,您可以使用call 和apply (as @elclanrs points out in his answer) 并始终使用this.form:

 ContactForm.reset.call({form: document.getElementById("someForm")});

【讨论】:

  • @elclanrs 的解决方案很好,并且可能是“严格技术”的更正确答案,但您的答案更接近我的想法,并且更容易理解......
【解决方案2】:

在 JavaScript 的对象语法中,如果没有任何特殊字符,则不需要引号:

var obj = {
   key: function() {
     ...
   },
   ...
}

Paamayim Nekudotayim 在 JavaScript 中没有位置,因为没有类,没有静态方法。但是 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!

【讨论】:

    【解决方案3】:

    你可以把它变成这样的一个类:

    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);
    

    【讨论】:

    • 那么我将实例化一个对象,这是我试图避免的......因为我不想跟踪那个实例,也不想创建多余的实例。好吧,也许我做得太过分了,你的代码完全可以(谢谢),从务实的角度来看,实际上可能是最好的答案。
    【解决方案4】:

    阅读 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 中已经存在的这种“功能”,尽管形式不同,不太直接。

    此外,肖恩·维埃拉的方法已完成:

    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();
    

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-04-20
      • 2010-09-09
      • 2015-12-18
      • 1970-01-01
      • 2012-11-07
      • 2014-10-05
      • 2011-11-04
      相关资源
      最近更新 更多