Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   КАКОЙ КОД ОПТИМАЛЬНЕЕ (https://javascript.ru/forum/misc/24163-kakojj-kod-optimalnee.html)

Livanderiaamarum 19.12.2011 23:10

КАКОЙ КОД ОПТИМАЛЬНЕЕ
 
Как быстрее?

function q ()
{
      function w (){}//опишем функцию
      w()//вызовем её
}
q()


или

function q ()
{
      var self = arguments.callee
      self.w()//вызовем функцию
}
q.w = function (){}//опишем функцию
q()


при условии что q() мы будем вызывать часто

trikadin 19.12.2011 23:11

Первый. Плюс он короче и читабельнее.

Livanderiaamarum 19.12.2011 23:15

Цитата:

Сообщение от trikadin (Сообщение 144574)
Первый. Плюс он короче и читабельнее.

Ясно, поделитесь почему?:)

я думал что в первом случае при входе в контекст функции q() каждый раз создается функция w()

во втором случае же функция w() уже создана и хранится в памяти и не тратится время на её создание. мы просто обращаемся к ней по ссылке.

Я ДУМАЛ ТАК. а как на самом деле?

trikadin 19.12.2011 23:20

Цитата:

Сообщение от Livanderiaamarum
во втором случае же функция w() уже создана и хранится в памяти и не тратится время на её создание. мы просто обращаемся к ней по ссылке.

Я ДУМАЛ ТАК. а как на самом деле?

Если говорить про однократное использование - то первый вариант короче в силу меньшего времени на поиск переменной в различных скопах. Если про многократное - то да, ф-цию лучше закешировать, второй вариант лучше. Но я бы сделал так, т.к. arguments.callee в последнее время не рекомендуется к употреблению:

var w;
(function(){
 var q= function(){};
 w= function(){
  q();
 };
})()

melky 20.12.2011 00:08

Цитата:

Сообщение от Livanderiaamarum (Сообщение 144572)
Как быстрее?

function q ()
{
      function w (){}//опишем функцию
      w()//вызовем её
}
q()


или

function q ()
{
      var self = arguments.callee
      self.w()//вызовем функцию
}
q.w = function (){}//опишем функцию
q()


при условии что q() мы будем вызывать часто

я бы сделал так :


var q = function(){

    var w = function(){ /*...*/ }; 

    q = function(){
        return w();
    };

    return q();
}

Livanderiaamarum 20.12.2011 00:13

Цитата:

Сообщение от melky (Сообщение 144592)
я бы сделал так :


var q = function(){

    var w = function(){ /*...*/ }; 

    q = function(){
        return w();
    };

    return q();
}

я понял что тут происходит, но я не понял как это связано с кешированием функций?

melky 20.12.2011 00:17

перед тем, как ответить на твой вопрос, расскажи, что ты понял :)

PS если бы ты полностью понял, вопроса бы у тебя не возникло

Livanderiaamarum 20.12.2011 00:22

Цитата:

Сообщение от melky (Сообщение 144595)
перед тем, как ответить на твой вопрос, расскажи, что ты понял :)

PS если бы ты полностью понял, вопроса бы у тебя не возникло

q() при вызове перезаписывает себя, и сохраняет в себе w , кэширует, ясно)

melky 20.12.2011 00:31

ответ неверный на 50%:)

сохраняет в себе, это значит "добавляет свойство к себе"

вот этот код как раз это делает


function q ()
{
      var self = arguments.callee;
      self.w = function(){};
      self.w();
}
q()

Livanderiaamarum 20.12.2011 00:35

Цитата:

Сообщение от melky (Сообщение 144604)
ответ неверный на 50%:)

сохраняет в себе, это значит "добавляет свойство к себе"

вот этот код как раз это делает


function q ()
{
      var self = arguments.callee;
      self.w = function(){};
      self.w();
}
q()

я не свойство имел ввиду а скоп)

melky 20.12.2011 00:39

таки да.
Цитата:

Сообщение от Livanderiaamarum (Сообщение 144594)
я понял что тут происходит, но я не
понял как это связано с кешированием функций?

Цитата:

Сообщение от Livanderiaamarum (Сообщение 144598)
q() при вызове перезаписывает себя, и сохраняет в области видимости w , кэширует, ясно)

я же говорил :)

Иваннн 21.12.2011 12:42

Про варианты функций
 
"вот этот код как раз это делает"
Вроде не совсем то
Если я правильно понял, то в варианте Melky кэшируется w, и доступен сам объект функции w только через внешнюю функцию, при этом this у w=global obj
у Livanderiaamarum кэшируется тоже w, но this (при обращении через self ссылается на объект хозяин свойвства, то есть q) и объект функции доступен в глобальном пространстве через q.w.

Livanderiaamarum 21.12.2011 14:03

Цитата:

Сообщение от Иваннн (Сообщение 144923)
в варианте Melky кэшируется w, и доступен сам объект функции w только через внешнюю функцию

вот это я и не понял вначале, я подумал что за бред? где это можно использовать? это же запарывает функцию q()

Иваннн 21.12.2011 14:40

Цитата:

Сообщение от Livanderiaamarum (Сообщение 144935)
вот это я и не понял вначале, я подумал что за бред? где это можно использовать? это же запарывает функцию q()

На сколько я понимаю q -это всего лишь ссылка на объект функции. При новом присваивании значения ссылке q ссылка просто начинает указывать на другой объект (на
function(){ return w();}

)
a объект на который ссылалась ссылка до изменения удалился бы, если бы не было вызвано замыкание (из глобального пространства есть ссылка на объект функции, "задекларированный" в виде выражения в другой функции ), а так как замыкание есть, то объект висит в памяти, и единственный способ к нему добраться, т.е к его области видимости - только через новую q.
Как я понимаю операцию можно разделить на две части. Не обязательно изменять саму ссылку q, можно внутренний объект функции привязать к любой переменной (т.е. ссылке, допустим у) видимой в глобальном объекте, а потом q=null или delete q, и работать с у.

Livanderiaamarum 21.12.2011 14:43

Цитата:

Сообщение от Иваннн (Сообщение 144948)
На сколько я понимаю q -это всего лишь ссылка на объект функции. При новом присваивании значения ссылке q ссылка просто начинает указывать на другой объект

это и запарывает функцию по имени q() и я не могу больше её использовать.

но наверное человек работал ИСХОДЯ ИЗ ДАННОГО МНОЙ примера) и думал что внутри q() не будет ни какого кода кроме w()

melky 21.12.2011 15:42

Цитата:

Сообщение от Livanderiaamarum (Сообщение 144952)
это и запарывает функцию по имени q() и я не могу больше её использовать.

но наверное человек работал ИСХОДЯ ИЗ ДАННОГО МНОЙ примера) и думал что внутри q() не будет ни какого кода кроме w()

это паттерн такой. и придуман он для того, чтобы не создавать каждый раз что-нибудь (кэшировать) и чтобы не захламлять скоп.

один пример - кеширование объекта настроек по-уолчанию.
function ajax(){

    var def = {
         "async":true
    };

    ajax = function(obj){
        // def сохранён в замыкании
        extend(obj, def);
    };

    ajax.apply(this,arguments);

};

ещё пример - удаление ветви кода при использовании опр. браузера.
// было :
function addScript(url, callback, parent){

    var script = document.createElement("script"),
        // ищем head каждый раз.
        parent = parent || document.getElementsByTagName('head')[0];



     // для IE<9.
    if('\v'=='v'){
        script.type = "text/javascript";
        script.onreadystatechange = function(){
            //this == script, но я буду использовать переменную
            if(script.readyState == "complete" || script.readyState == "loaded"){
                callback();
                // memory leak
                script.onreadystatechange = script.onload = null;
            }
        };
    } else {
        // нормальное поведение.
        script.onload = callback;
    }

    script.src = url;    
    parent.appendChild(script);
};

// стало :
function addScript(){

    // ищется только один раз
    var head = document.getElementsByTagName('head')[0];

    if('\v'=='v') // ie < 9

        addScript = function(url, callback){

            var script = document.createElement('script');

            script.onreadystatechange = function(){
                if(this.readyState == "complete" || this.readyState == "loaded"){
                    callback();
                    script.onreadystatechange = script.onload = null;
                };
            };
            
            script.type = "text/javascript";

            script.src = url;

            head.appendChild(script);
        };

    else 

        addScript = function(url, callback){

            var script = document.createElement("script");

            script.src = url;

            script.onload = callback;

            head.appendChild(script);

        };

    addScript.apply(this, arguments);
};


да, немного больше кода, немного больше запутанность кода. но , если ясно понимать, что тут происходит, всё становится понятным.

не ищется каждый раз head. конечно, в первом случае head можно было сохранить в переменной ещё до функции, но в данном случае мы это не рассматриваем.

во втором случае не просчитывается условие. следует понимать, что в данном случае это мало чего сэкономило, но в функции, в которой каждая строчка является if'ом, проверяющим браузер (или вообще любой другой if), это может сэкономить время. ты же любитель муравьиной оптимизации, Livanderiaamarum ?

во втором случае на выходе получается чистая функция. так сказать, "скомпилированная под конкретный браузер". в этом можно убедиться, вызвав addScript.toString();

Livanderiaamarum 21.12.2011 15:52

Цитата:

Сообщение от melky (Сообщение 144965)
это паттерн такой. и придуман он для того, чтобы не создавать каждый раз что-нибудь (кэшировать) и чтобы не захламлять скоп.

спасибо, не знал)))) шикарная штука)


Часовой пояс GMT +3, время: 20:51.