使用John Resig的javascript继承时缓存它

时间:2017-01-17 10:14:08

标签: javascript jquery class inheritance

我在几个项目中使用John Resig's javascript inheritance patternbetter formatted version)。

使用这种模式,我可以从另一个类this.otherMethod()中调用一个类方法。

但是,我的类方法通常包含具有自己的作用域的代码,并且已经定义了自己的this,例如ajax成功处理程序或$.each等jQuery方法。

这样的事情很典型:

 var AppWidget = Class.extend({
    /**
     * Initialize and set any defaults
     */
    init: function(options) {

        var _this = this;
        var defaults = {
        };
        _this.options = $.extend(true, defaults, options);
        return _this;
    },

    /**
     * Do something involving ajax
     */
    someAjaxyFunction:function(){
        var _this = this;

        $.ajax({
            type: "POST",
            url: "page.php",
            data: dataString,
            success: function(data) {
                _this.someFollowupFunction(data)
            }
        }); 
    },

    /**
     * Do some followup work
     */
    someFollowupFunction:function(data){
        var _this = this;
        $.each(data,function () {
            _this.someOtherFunction(this);
        });
    },

    /**
     * Do some other work
     */
    someOtherFunction:function(thing){
        var _this = this;
         //...
    }
});

它会被称为:

var widget = new AppWidget();
widget.someAjaxyFunction();

但是,我想知道是否有更好的方法来处理在方法中使用的缓存this。将var _this = this;添加到每个类方法的顶部都可以,但是非常繁琐,而且在编写新方法时经常会忘记它。

是否有一些聪明的方法可以使_this在所有类方法中自动可用,或者更方便的方法是引用除this关键字以外的类?

1 个答案:

答案 0 :(得分:1)

正如您所提到的那样,您可以从John修改Class.extend实现,理论上可以将_this变量作为函数参数注入。

这当然在很大程度上取决于您希望对当前运行的代码进行多少更改。

在我的示例中,我将_this参数添加到函数参数列表中,作为所有函数的第一个参数。这将以下列方式更改您的示例类(完整示例可以在下面的代码段中找到):

var Example = Class.extend({
  method: function(_this, timeout) {
    // some code
  },
  callback: function(_this, arg1) {
    // some code
  }
});

var example = new Example();
example.method(5);

如你所见,_现在这是第一个参数。但是,如何调用类中的方法不会改变,您仍然可以调用example.method(15),它将使用预先填充的_this参数调用method(通过{{1分配给参数列表)方法)

这仍然允许你使用Class.extend实现,它甚至可以提供正确的回调(nl:之后的派生类,例如这里)

this._super()

John的代码所需的更改(最初来自John's blog,在Secrets of a JavaScript Ninja内进行了更深入的讨论),与此类似:

var Sample = Example.extend({
    method: function(_this, timeout) {
    this._super(timeout);
    console.log('I was called from sample');
  },
  callback: function(_this) {
    console.log('I am supplied from Sample');
  }
});

var sample = new Sample();
sample.method(10);

主要的变化是/* Simple JavaScript Inheritance * By John Resig http://ejohn.org/ * MIT Licensed. */ // Inspired by base2 and Prototype (function(){ var initializing = false, fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/; // The base Class implementation (does nothing) this.Class = function(){}; function convertArgumentsToArray( args ) { return Array.prototype.slice.apply( args ); } // Create a new Class that inherits from this class Class.extend = function(prop) { var _super = this.prototype; // Instantiate a base class (but only create the instance, // don't run the init constructor) initializing = true; var prototype = new this(); initializing = false; // Copy the properties over onto the new prototype for (var name in prop) { // Check if we're overwriting an existing function prototype[name] = typeof prop[name] == "function" && typeof _super[name] == "function" && fnTest.test(prop[name]) ? (function(name, fn){ return function() { var tmp = this._super; // Add a new ._super() method that is the same method // but on the super-class this._super = _super[name]; // The method only need to be bound temporarily, so we // remove it when we're done executing var ret = fn.apply(this, [this].concat( convertArgumentsToArray( arguments ) )); this._super = tmp; return ret; }; })(name, prop[name]) : (function(fn) { return function() { var ret = fn.apply(this, [this].concat( convertArgumentsToArray( arguments ) )); return ret; } })(prop[name]); } // The dummy class constructor function Class() { // All construction is actually done in the init method if ( !initializing && this.init ) this.init.apply(this, arguments); } // Populate our constructed prototype object Class.prototype = prototype; // Enforce the constructor to be what we expect Class.prototype.constructor = Class; // And make this class extendable Class.extend = arguments.callee; return Class; }; })(); 上下文会自动注入参数列表。

仍然可以进行的优化是检查参数列表中是否定义了this变量,目前,如果你有任何参数,你应该总是添加{{1}参数作为第一个参数。

您可以在代码段或jsfiddle here

中看到完整的工作示例

_this