Я смотрел плагин для плагинов для плагинов jQuery, я нахожу это в порядке, но есть один главный недостаток в дизайне или, может быть, просто то, что я не могу понять.
Когда я создаю плагины на данный момент, мне легко определить общедоступные методы и частные методы, к которым имеет доступ только плагин.
Когда я попытался сделать что-то подобное на плите котла, меня сорвали.
;(function ( $, window, document, undefined ) {
// Create the defaults once
var
pluginName = "defaultPluginName",
defaults = {
propertyName: "value"
};
// The actual plugin constructor
function Plugin ( element, options ) {
this.element = element;
this.settings = $.extend( {}, defaults, options );
this.defaults = defaults;
this.name = pluginName;
this.init();
}
Plugin.prototype.init = function() {
console.log('init')
console.log(this)
this.yourOtherFunction();
}
Plugin.prototype.yourOtherFunction = function () {
console.log('yourOtherFunction')
console.log(this)
this.yourOtherFunction2();
}
Plugin.prototype.yourOtherFunction2 = function () {
privateFunction().bind(this)
}
var privateFunction = function() {
console.log('private')
console.log(this)
}
// A really lightweight plugin wrapper around the constructor,
// preventing against multiple instantiations
$.fn[ pluginName ] = function ( options ) {
return this.each(function() {
if ( !$.data( this, "plugin_" + pluginName ) ) {
$.data( this, "plugin_" + pluginName, new Plugin( this, options ) );
}
});
};
})( jQuery, window, document );
$(document).defaultPluginName()
В любом случае вы можете видеть, что функция privateFunction - это область действия объекта window, но я хочу, чтобы она могла это сделать, - это объединить ее с экземпляром Plugin или в основном "это" из методов прототипа.
То, что я не хочу делать, пропускает область в каждую частную функцию как аргумент функции!
Итак, как я могу привязать область?
Console output
init
Plugin { element=document, settings={...}, defaults={...}, more...}
yourOtherFunction
Plugin { element=document, settings={...}, defaults={...}, more...}
private
Window index.html <-- I want Plugin, not window
Заменить:
Plugin.prototype.yourOtherFunction2 = function () {
privateFunction().bind(this)
}
С
Plugin.prototype.yourOtherFunction2 = function () {
privateFunction.apply(this,arguments);
}
Вы вызываете privateFunction
а затем привязываете this
как область для своего результата.
Поэтому используйте (как сказал @Khanh_TO):
Plugin.prototype.yourOtherFunction2 = function () {
privateFunction.apply(this,arguments);
}
Вместо:
Plugin.prototype.yourOtherFunction2 = function () {
privateFunction().bind(this)
}
Подробнее:
bind
возвращает копию функции, на которую вызывается (результат privateFunction
в вашем случае) после применения области, в которой вы прошли (this
в вашем случае). Что такое bind
, это что-то вроде:
Function.prototype.bind = function(scope) {
var _function = this;
var _args = [];
for (var i = 0, len = arguments.length-1; i < len; i++){ _args[i] = arguments[i+1]; }
return function() {
// returns the same function on which is called (not the same Function object, but
// another with same properties) with 'this' equal to the first parameter and
// the remaining specified parameters as parameters of the function returned
return _function.apply(scope, _args);
}
}
например. myFunction.bind(newScope, param1, param2,...)
→ возвращает анонимную функцию, которая по очереди возвращает функцию myFunction(param1, param2,....)
с установкой this = newScope
.
Таким образом, как доказательство концепции, этот код также сработал бы:
Plugin.prototype.yourOtherFunction2 = function () {
privateFunction.bind(this)();
}
но вы должны использовать первый, поскольку последний делает то же самое с дополнительными проходами.
arguments
- это массив.