【问题标题】:How to change Prototype class declarations into jquery?如何将原型类声明更改为 jquery?
【发布时间】:2011-10-10 08:22:45
【问题描述】:

我正在处理我的 Rails 3.1 迁移,让 jquery 和原型和平共处变得越来越难。我正在研究一种将我的原型方式实现的 js 文件更改为 jquery 格式的方法。

我大量使用原型方式来声明类和子类:

// properties are directly passed to `create` method
var Person = Class.create({
  initialize: function(name) {
    this.name = name;
  },
  say: function(message) {
    return this.name + ': ' + message;
  }
});

// when subclassing, specify the class you want to inherit from
var Pirate = Class.create(Person, {
  // redefine the speak method
  say: function($super, message) {
    return $super(message) + ', yarr!';
  }
});

var john = new Pirate('Long John');
john.say('ahoy matey');
// -> "Long John: ahoy matey, yarr!"

我已阅读有关 John Resig 的脚本:http://ejohn.org/blog/simple-javascript-inheritance/。这是要走的路吗?还是我应该选择其他方法?

我有大约 15 个 js 文件(每个文件一个类)。我愿意为这次迁移花一些时间,所以我想把它做好。感谢您的专业帮助!

【问题讨论】:

    标签: javascript jquery ruby-on-rails ruby-on-rails-3.1 prototype-programming


    【解决方案1】:

    这是使用普通函数实现示例的一种可能方法。

    function Person(name) {
      this.name = name;
    }
    
    Person.prototype.say = function (message) {
      return this.name + ": " + message;
    };
    
    function Pirate(name) {
      this._super = Person.prototype;
      this._super.constructor.apply(this, arguments);
    }
    
    Pirate.prototype.say = function (message) {
      return this._super.say.apply(this, arguments) + ", yarr!";
    };
    
    john = new Pirate("Long John");
    john.say("ahoy matey");
    

    您可能希望将继承操作提取到一个函数中,但这为您提供了基本思路。

    【讨论】:

      【解决方案2】:

      这是 Jimmy 示例的稍微改进的版本。首先,我要添加一个额外的函数,帮助您更方便地定义原型链。你也可以使用Object.create(),但目前还不是所有浏览器都支持这个功能,所以这个功能应该更防弹一点:

      // A convenient function to define prototype chain
      
      function inheritPrototype(child, parent) {
        function F(){}
        F.prototype = parent.prototype;
        child.prototype = new F();
        // set the constructor back to the original, explained later
        child.prototype.constructor = child;
      }
      

      然后定义对象。请注意额外的函数setName,它使我们能够设置Person 的名称。 (没关系,在 JS 中通常不需要 getter/setter)。还要注意在 Pirate 函数定义后额外的 inheritPrototype 调用。

      function Person(name) {
        this.name = name;
      }
      
      Person.prototype.say = function (message) {
        return this.name + ": " + message;
      };
      
      Person.prototype.setName = function(name) {
        this.name = name;
      };
      
      function Pirate(name) {
        this._super = Person.prototype;
        this._super.constructor.apply(this, arguments);
      }
      
      inheritPrototype(Pirate, Person);
      
      Pirate.prototype.say = function (message) {
        return this._super.say.apply(this, arguments) + ", yarr!";
      };
      
      var john = new Pirate("Long John");
      john.say("ahoy matey");
      

      这种风格可以让你自动调用父函数,如果它们和它们的父函数相同,你不必重写它们中的每一个。此外,这不会阻止您重新定义父级已经存在的函数(在这种情况下,say 被覆盖)。请记住,所有功能都是单向的,这意味着如果您在子代中覆盖一个功能,则父代的功能保持不变。一个例子:

      // Should result in John "The Pirate" Long: ahoy matey, yarr! 
      // instead of how it was defined in Person 
      john.setName('John "The Pirate" Long');
      john.say('ahoy matey');
      
      // Notice that even though Pirate redefined say function, it
      // still works as defined in Person, if it's called on a Person object
      var president = new Person("Obama");
      president.say('Vote for me!');
      

      如果child.prototype.construtor 被重新定义为子对象(替换原型将其设置为父对象的构造函数),也可以使用此样式检查对象类型。 John 既是 Person 又是 Pirate(因为 Pirate 继承自 Person)。一个例子:

      john instanceof Person
      > true
      john instanceof Pirate
      > true
      

      由于总统直接是 Person 对象而不是 Pirate,因此结果如下:

      president instanceof Person
      > true
      president instanceof Pirate
      > false
      

      【讨论】:

      • +1 感谢您的想法!我将使用 Jimmy 的示例,看看是否需要添加它。谢谢!
      • @hade 如果您打算实现继承,就像在原始示例中一样,我建议您至少使用inheritPrototype 函数,而不是重新定义子对象中的每个函数。这就是原型继承的全部思想。
      【解决方案3】:

      jQuery 没有类的概念。它是一个为抽象浏览器差异和简化常见操作过程而构建的库; DOM manipulationAJAXevent handling

      【讨论】:

      • 感谢@Matt 的回答。几年前,由于缺少类,我选择了 Prototype(我更喜欢使用类)。现在原型正在消失,我想知道在我的情况下迁移的最佳方式是什么。
      • @hade:我从来都不是 JavaScript 类中的 hacking 的粉丝。 JavaScript 应该被它所采用的语言所接受(具有原型继承)。
      • 好的,既然我已经用 Prototype 类“hack”污染了我的代码,我应该如何摆脱它?你如何保持你的js代码井井有条?您是否使用像模块模式(或类似)这样的设计模式。
      【解决方案4】:

      看看 Dean Edward 的 Base.js:http://dean.edwards.name/weblog/2006/03/base/

      var object = new Base;
      object.method = function() {
        alert("Hello World!");
      };
      object.extend({
        method: function() {
          // call the "super" method
          this.base();
          // add some code
          alert("Hello again!");
        }
      });
      object.method();
      // ==> Hello World!
      // ==> Hello again!
      

      如果您直接调用 _super,如果 super 方法也使用 this._super,您可能会遇到问题 - 然后作为无限循环运行,因为您始终传递与“this”相同的对象。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-08-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-01-12
        • 1970-01-01
        相关资源
        最近更新 更多