Выявление метода, который находится внутри замыкания
Когда мы создаем метод внутри замыкания, он становится закрытым для этого закрытия и не может быть доступен, пока мы его не выставим каким-либо образом.
Как он может быть выставлен?
Ответы
Ответ 1
Вы можете вернуть ссылку на него...
var a = function() {
var b = function() {
// I'm private!
alert('go away!');
};
return {
b: b // Not anymore!
};
};
Посмотрите на jsFiddle.
Вы также можете привязать его к объекту window
. Но я предпочитаю метод выше, иначе вы подвергаете его с помощью глобальной переменной (являющейся свойством объекта window
).
Ответ 2
Вам нужно каким-то образом передать его наружу.
Пример: http://jsfiddle.net/patrick_dw/T9vnn/1/
function someFunc() {
var privateFunc = function() {
alert('expose me!');
}
// Method 1: Directly assign it to an outer scope
window.exposed = privateFunc;
// Method 2: pass it out as a function argument
someOuterFunction( privateFunc );
// Method 3: return it
return privateFunc;
}
someFunc()(); // alerts "expose me!"
function someOuterFunction( fn ) {
fn(); // alerts "expose me!"
}
window.exposed(); // alerts "expose me!"
Ответ 3
Вы раскрываете функции или свойства замыкания, внутренне объявляя их в этой области (которые могут меняться в зависимости от вызова).
function example(val) {
var value = val;
this.getVal = function() {
return value;
}
this.setVal = function(v) {
value = v;
}
}
var ex = new example(2);
ex.getVal(); // == 2
ex.setVal(4); // == null
ex.getVal(); // == 4
Способы, объявленные в этом, могут обращаться к переменным, объявленным с помощью var, но не наоборот. round.
function example(val) {
var value = val;
var double = function(v) {
return 2 * v;
}
this.getDouble = function() {
return double(value);
}
}
var ex = new example(2);
ex.getDouble(); // == 4
Функция закрывается по области. То, что вы хотите сделать, это вернуть ссылку на функцию, которая имеет доступ к требуемой области, поэтому вы можете вызвать ее позже.
Если вам нужно создать функцию, которая вызывает определенный метод в какой-то более поздний момент,
var ex = new example(2);
var delayed_call = function() {
return(ex.getDouble()); // == 4, when called
}
setTimeout(delayed_call, 1000);
Если определение области видимости является проблемой,
var ex = new example(2);
var delayed_call = (function(ex_ref) {
return function() {
return(ex_ref.getDouble()); // == 4, when called
}
})(ex); // create a new scope and capture a reference to ex as ex_ref
setTimeout(delayed_call, 1000);
Вы можете включить большинство из этого с менее читаемым примером,
setTimeout((function(ex_ref) {
return function() {
return(ex_ref.getDouble()); // == 4, when called
})(new example(2)))
, 1000
);
setTimeout - это просто удобный способ продемонстрировать выполнение в новой области.
var ex = new example(2);
var delayed_call = function() {
return(ex.getDouble());
}
delayed_call(); // == 4
Ответ 4
В целях производительности вы можете вызвать его следующим образом:
var a = (function(){
function _a(){}
_a.prototype = (function(){
var _test = function(){ console.log("test"); };
return {
test: _test
}
}());
return new _a();
}());
// usage
var x = a;
x.test(); // "test"