Есть спецы по JavaScript?
Feb. 1st, 2014 10:28 pmПытаюсь допилить код MP3-плеера для сайта, написанного на JS. Он начинается со строки:
Немного упростим задачу. Я написал функцию внутри объекта:
Как мне вызвать эту функцию извне? playerExEngine.i_hate_javascript() не работает, просто i_hate_javascript(), разумеется, тоже. Чего я только не перепробовал, не работает и всё тут. =(
var playerExEngine = new playerFlash(function() {
Немного упростим задачу. Я написал функцию внутри объекта:
var playerExEngine = new playerFlash(function() {
function i_hate_javascript () {
alert('JavaScript sucks!');
}
});
Как мне вызвать эту функцию извне? playerExEngine.i_hate_javascript() не работает, просто i_hate_javascript(), разумеется, тоже. Чего я только не перепробовал, не работает и всё тут. =(
no subject
Date: 2014-02-01 06:55 pm (UTC)это дурацкие яваскриптовые замыкания
вообще, я бы вывел нужную функцию в виде функции вовне, и с ней бы работал.
no subject
Date: 2014-02-01 07:21 pm (UTC)(а трекинг-то что показывает, кстати?)
Перемудрили, кажется. Почему бы не запихнуть функцию прямо в тип playerFlash, когда вы его определяете? А то, вроде, получается так: тип определили (или он библиотечный? на встроенный-то точно не похож), потом только в нем создается новая переменная, и при ее инициации определяется функция. Возможно, компилятор сходит в этот момент с ума.
И согласен с предыдущим оратором - в чем проблема определить функцию "снаружи"?
no subject
Date: 2014-02-01 07:36 pm (UTC)no subject
Date: 2014-02-01 09:07 pm (UTC)JavaScript не sucks. Там функция -- это тоже объект и от отличается от обычных объектов, которые с полями и методами. Похоже на Runnable из Java. Он создаётся в тот момент, когда исполняется код, содержащий определение функции. Само тело функции не исполняется до тех пор, пока Вы его не вызовете.
Например, в Джава
new Runnable() { public void run() { new Runnable() { public void run() { System.out.println("I hate world"); } } } }метод run() не вызовется, он просто создастся.
В момент создания функции, происходит замыкание (closure) то есть, функция "фотографирует" все переменные, которые существовали в момент её создания. В Javascript замыкание полноценное, а Java потребует от Вас сделать переменные final (то есть, Java не умеет полноценно "фотографировать").
По Вашему коду.
Что делает конструктор playerFlash (я не в курсе)? Вы ему передали безымянную функцию. Внутри этой безымянной функции есть код, который создаёт функцию с именем i_hate_javascript.
Если конструктор playerFlash не исполняет безымянную функцию, которую Вы ему передаёте, то достучаться до функции i_hate_javascript нельзя, ибо она ещё не создана.
Если конструктор исполняет переданную ему функцию, то достучаться до неё можно, при условии, если вы знаете, куда конструктор положил результат.
Если исключить неизвестный мне конструктор и написать вот так
function f1() { return function f2() { return function f3() { alert('I hate world'); } } }то есть, сделать, чтобы каждая функция возвращала вложенную, то вызвать внутреннюю можно вот так
f1()()()
то есть, три вызова: вызвать f1, результатом будет f2, вызвать f2, результатом будет f3, вызвать её.
Скобки означают вызов.
Можно написать иначе
a1 = function () { a2 = function() { a3 = function() { alert('I hate world'); } } }Тогда каждая функция будет создавать другую в момент вызова и класть её в свою переменную
Тогда, чтобы вызвать самую внутреннюю, надо сделать три вызова по очереди
a1(); // создалась функция a2 и её можно вызывать
a2(); // создалась функция a3 и её можно вызывать
a3(); // покажет алерт
Обратите внимание, что переменные не вложенные, они все "верхнего уровня".
Чтобы воссоздать множество вложенных объектов, нужно использовать слова this и new
b1 = new function() { this.b2 = new function() { this.b3 = function() { alert('I hate world'); } } }Здесь new не использовано в последнем случае
new превращает функцию в конструктор объекта и выполняет её сразу. конструктор возвращает this, то есть, "содержимое" объекта с полями и методами (как в Java)
То есть, строчка b1= вызвала функцию-конструктор и положила её содержимое в b1
содержимое сконструировалось таким образом, что оно состоит из переменной b2, в которую положилось ещё вложенное содержимое, которое состоит из переменной b3. Внутри этой переменной лежит уже не object, а функция.
Чтобы её вызвать, надо написать так
b1.b2.b3();
no subject
Date: 2014-02-02 01:10 pm (UTC)PHP, разумеется. Там в 90% случаев можно легко обойтись без подобной мути. Я уже решил вопрос, повесив внутри типа обработчик на «искуственно» вызываемое событие, но спасибо за развёрнутый ответ. Некоторые вещи я и не знал. =)
no subject
Date: 2014-02-02 04:10 am (UTC)playerExEngine.пожалуйста.i_hate_javascript()
no subject
Date: 2014-02-02 10:54 am (UTC).
Но есть два варианта
например
var playerFlash = function(){};
playerFlash.prototype.foo = function () {
alert("JavaScript sucks!");
}
var playerExEngine = new playerFlash;
тогда позвать просто playerExEngine.foo();
или
var playerExEngine = new playerFlash(function() {
//определяем явно и это плохо
playerExEngine.foo= function() {
alert("JavaScript sucks!");
}
});
playerExEngine.foo();
или более правильно (это должно срабоать если playerflash исполнит переданную ему как параметр функцию)
var playerExEngine = new playerFlash(function() {
this.foo = function () {
alert('JavaScript sucks!');
}
});
или можно повесить хэндлер на на событие - скажем кастом эвент.
no subject
Date: 2014-02-02 01:12 pm (UTC)Спасибо. Я так и сделал.
no subject
Date: 2014-02-02 01:15 pm (UTC)