gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-11-29 23:55:57 25 4
gpt4 key购买 nike

我使用 John Resig's javascript inheritance pattern ( better 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 关键字以外的类?

最佳答案

正如您提到的,您愿意修改 John 的 Class.extend 实现,理论上您可以将 _this 变量作为函数参数注入(inject)。

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

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

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

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

如您所见,_this 现在始终是第一个参数。但是,调用类中方法的方式没有改变,您仍然可以调用 example.method(15) ,它会调用带有预填充 _this 参数的 method(通过Class.extend方法赋值给参数列表)

这仍然允许您使用 this._super() 实现,它甚至会提供正确的回调(nl:之后派生类的回调,例如此处)

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

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

/* 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 上下文自动注入(inject)到参数列表中。

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

您可以在此处的代码片段或 jsfiddle here 上看到完整的工作示例

/* 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;
};
})();


var Example = Class.extend({
method: function(_this, timeout) {
console.log('timeout defined is ' + timeout);
setTimeout(function() {
_this.callback( 15 );
}, timeout);
},
callback: function(_this, arg1) {
console.log('callback from _this argument, current context: ', this);
console.log(_this === this);
console.log(arg1 === 15);
}
});

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 example = new Example();
example.method(5);

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

关于javascript - 使用 John Resig 的 javascript 继承时缓存它,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41694383/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com