Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Цепочка функций (https://javascript.ru/forum/misc/6967-cepochka-funkcijj.html)

sartas 08.01.2010 19:23

Цепочка функций
 
Сделал аналог цепочек jQuery.

код:
(function(){

var 
    window = this,
    undefined,

    jQuery = window.jQuery = window.$ = function( selector, context ) {
        return new jQuery.fn.init( selector, context );
    };

jQuery.fn = jQuery.prototype = {
    init: function( selector, context ) {

        // Если selector - объект, возвращаем его
        if ( selector.nodeType ) {
            this[0] = selector;
            return this;
        }

        // В противном случае берем элемент по id
        var elem = document.getElementById( selector );
        var ret = jQuery( elem );

        return ret;
        
    },

    // Наши функции
    raz: function() {
        this[0].innerHTML += 'первая пошла, ';
    return this;
    },
    
    dva: function() {
        this[0].innerHTML += 'вторая пошла, ';
    return this;
    },
    
    tri: function() {
        this[0].innerHTML += 'третья пошла ';
    return this;
    }
};

jQuery.fn.init.prototype = jQuery.fn;

})();


sample:
<div id='sampleid'></div>
    <script type="text/javascript">
    
        $('sampleid').raz().dva().tri();

    </script>


Можно ли использовать такую реализацию цепочек? Какие могут возникнуть проблемы?

Octane 08.01.2010 19:36

что-то куча связей fn-init-prototype и ненужных оберток
function $(…) {
    return new $.wrapper(…);
}

$.wrapper = function (…) {
    this… = …;
};

$.wrapper.prototype = $.prototype = {
    constructor: $,
    raz: …,
    dva: …,
    tri: …
};

Проблем вроде нет, если удобно, ни что не мешает использовать.

Dmitry A. Soshnikov 09.01.2010 01:26

Цитата:

Сообщение от sartas
var window = this,

Зачем это?

sartas 09.01.2010 16:14

Это из jQuery

var 
// Will speed up references to window, and allows munging its name.
window = this,
// Will speed up references to undefined, and allows munging its name.
undefined,

Dmitry A. Soshnikov 09.01.2010 16:41

Цитата:

Сообщение от sartas
Это из jQuery

Выделить все

var
// Will speed up references to window, and allows munging its name.
window = this,
// Will speed up references to undefined, and allows munging its name.
undefined,

Тот, кто это написал (я не знаю, Резиг или нет) не понимал две важные вещи:

1. Самое главное - если он вызывает в дальнейшем код в контексте this, который был присвоен изначально в локальную переменную window (т.е. глобальный объект), то this - всегда будет работать быстрее, т.к. this не резолвится вообще, он определён единожды при входе в контекст, а вот локальная переменная window будет резолвится всегда при обращении. Так что, здесь имеет место быть явное недопонимание, как и почему "оно" так работает.

2. Есть принципиальная разница между объектом window и глобальным объектом (this в глобальном контексте - есть глобальный объект). Первый - это хост-объект, второй - это нативный объект. Да и не всегда, window - рекурсивная ссылка на глобальный объект; в некоторых реализациях это не так (хотя в стандарте - и в 3-ей, и в 5-ой редакциях это отмечается).

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

Если бы он сделал var window = window, было бы другое дело. А в его случае, удобней было бы всегда использовать this, который был бы определён только один раз, а не постоянно, как window.

sartas 09.01.2010 19:03

Спасибо.
А разработчикам jQuery это никто не смог объяснить?

PeaceCoder 09.01.2010 23:23

Цитата:

Сообщение от sartas
А разработчикам jQuery это никто не смог объяснить?

те кто юзают jQuery вобще походу не смотрели исходники... вот и юзайте дальше....

Volk_88 11.01.2010 19:31

Цитата:

window = this
Что касается данного выражения, думаю это было сделано из учета обращения к глобальному объекту в коде фреймворка, где this - не является глобальным объектом, пример:

1) Тут вполне можно вместо window поставить this
Цитата:

var window = this,
undefined,
_jQuery = window.jQuery,
_$ = window.$,

jQuery = this.jQuery = this.$ = function( selector, context ) {
// The jQuery object is actually just the init constructor 'enhanced'
return new jQuery.fn.init( selector, context );
}
2) В данном случае, window ссылается на Global, а вот this уже на jQuery (или я не прав? =) ), но вот я так и не понял, для чего реализована функция noConflict
Цитата:

(Релиз: 1.3.1, строка: 612)

jQuery.extend({
noConflict: function( deep ) {
window.$ = _$;

if ( deep )
window.jQuery = _jQuery;

return jQuery;
}
3) И тут понятное дело, this уже не указывает на Global
Цитата:

(Релиз: 1.3.1, строка: 612)

jQuery.event = {
handle: function(event) {
// returned undefined or false
var all, handlers;

event = arguments[0] = jQuery.event.fix( event || window.event );
Возможно я и ошибся, но введение данной переменной было необходимо, но в кое каких местах можно было обойтись без нее, но вот вопрос, а на сколько бы изменение в первом примере window на this дало бы выигрыш? может быть он настолько маленький, что разработчики jquery забили на него болт? =)

кстати, присоединяюсь к PeaceCoder, по поводу использования фреймвороков, порой зайдешь на форум, что бы найти алгоритм решения определенного вопроса, и порой появляется отвращения от всех тем(даже в разделе "для профи"), так как все только и знают, как решить вопрос с помощью фреймворков, а где же чистый javascript, про который наверно уже все забыли...а может и вообще не знали, в итоге появляется стада баранов, а не программистов, у которых спросишь "А ты знаешь javascript?" а они ответят: "да, конечно, это же jQuery", прям даже страшно становиться ))))

PeaceCoder 11.01.2010 19:47

Цитата:

Сообщение от Volk_88
Возможно я и ошибся, но введение данной переменной было необходимо, но в кое каких местах можно было обойтись без нее

если не вводить переменную window, которая покроет глобальный обьект window, то где бы ты не обращался к window - он и в африке будет window. для этого надо знать что такое область видимости переменных и как она работает.
Цитата:

Сообщение от Volk_88
у которых спросишь "А ты знаешь javascript?" а они ответят: "да, конечно, это же jQuery", прям даже страшно становиться ))))

согласен на все 100%. иногда сталкивался со знатоками фреймворков и когда начинаешь с ними разговаривать на эту тему аж отвращение появляется что к фреймворку, что к самому человеку, который не хочет понимать, что ты ему обьясняешь/говоришь.
фреймворки vs. JS это тоже самое как Assembler vs C++ или C++ vs VisualBasic
Как можно доказывать что высоко уровневый язык быстрее своего родителя? А таких не мало...

Volk_88 11.01.2010 19:57

Цитата:

Сообщение от PeaceCoder (Сообщение 40237)
если не вводить переменную window, которая покроет глобальный обьект window, то где бы ты не обращался к window - он и в африке будет window. для этого надо знать что такое область видимости переменных и как она работает.

благодарю за поправку, область видимость переменных то знаю (за что спасибо Dmitry A. Soshnikov), но вот сглупил и забылся из-за малого опыта программирования на JS.

Цитата:

Сообщение от PeaceCoder (Сообщение 40237)
Как можно доказывать что высоко уровневый язык быстрее своего родителя? А таких не мало...

имхо, таких людей лучше обходить стороной, толку от них мало, а мозг и нервы потреплют хорошо :)

Dmitry A. Soshnikov 11.01.2010 22:04

Цитата:

Сообщение от Volk_88
Что касается данного выражения, думаю это было сделано из учета обращения к глобальному объекту в коде фреймворка, где this - не является глобальным объектом

Да, если процент обращения к window в контекстах, где this не равен глобальному объекту большой, то это является оптимизацией. Но, тогда, идеологически верно было бы var window = window, что я и отметил, поскольку есть разница между window и глобальным объектом.

Цитата:

Сообщение от Volk_88
а вот this уже на jQuery (или я не прав? =) )

Прав, но вообще, зависит от выражения вызова и this определяется каждый раз при вызове, поэтому и этот метод extend можно вызвать так, где this будет не jQuery.

Цитата:

Сообщение от Volk_88
но вот я так и не понял, для чего реализована функция noConflict

Чтобы иметь возможность восстановить затёртые идентификаторы $ и jQuery (теоретически и практически, пользователь может использовать несколько фреймворков; noConflict позволит использовать $, например, из Prototype.js, а имя jQuery - из jQuery; также, там предусмотрен глубокий вариант восстановления, где восстанавливается и имя jQuery).

Цитата:

Сообщение от Volk_88
а на сколько бы изменение в первом примере window на this дало бы выигрыш

Здесь надо почитать про разрешение имён идентификаторов и цепь областей видимости.

Любой идентификатор разрешается - определяется, к какой области видимости в иерархической цепи, он относится. Это делается каждый раз при обращении к имени переменной. Соответственно, чем глубже контекст исполнения, тем дольше будет разрешаться идентификатор, определённый в более высоких контекстах исполнения (например, глобальном контексте).

(function () {
  (function () {
    (function () {
      alert([this, window]);
    })();
  })();
})();


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

В свою очередь, this, как уже было отмечено, никогда не разрешается, он определён один раз при входе в контекст. Поэтому в alert-e из примера выше значение this будет получено сразу - в отличие от window.

Однако, поскольку window - это host-объект, его разрешение (и вообще поведение) может зависеть от реализации.

Подробней про scope chain: http://javascript.ru/blog/Dmitry-A.-...j-vidimosti.-0

zeran 17.03.2011 13:51

Цитата:

Сообщение от Octane (Сообщение 39978)
что-то куча связей fn-init-prototype и ненужных оберток
function $(…) {
    return new $.wrapper(…);
}

$.wrapper = function (…) {
    this… = …;
};

$.wrapper.prototype = $.prototype = {
    constructor: $,
    raz: …,
    dva: …,
    tri: …
};

Проблем вроде нет, если удобно, ни что не мешает использовать.

-
А можно привести полный пример кода, а то не получается сделать рабочий пример :(( Говорит: $ is not defined

monolithed 18.03.2011 21:33

Цитата:

Сообщение от zeran
А можно привести полный пример кода, а то не получается сделать рабочий пример

<div id="div">text</div>

<script type="text/javascript">
function $(id) {
    if(this.$) return new $.wrapper(id);
}

$.wrapper = function(id) {
     if(typeof id == 'string' /* etc ... */) {
         this.id = document.getElementById(id);
     }
};

$.wrapper.prototype = $.prototype = {
    constructor: $,
    css: function(value) {
        for(i in value) {
            this.id.style[i] = value[i];
        }
         return this;
    }
    /* , 
    ....
   */
};

$('div').css({'color':'red', 'textTransform':'uppercase'});

</script>


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