Что является лучшим подходом к прототипу для нескольких типов - PullRequest
3 голосов
/ 29 сентября 2011

Игнорирование того факта, что это реализуется многими платформами.

Каков наилучший способ создания прототипов для нескольких типов объектов.* Например, я должен написать:

Element.prototype.bind = function(eventType, fn) {
    this.addEventListener(eventType, fn, false);
};
NodeList.prototype.bind = function(eventType, fn) {
    for (var i = 0, l = this.length; i < l; i++) {
        this[i].addEventListener(eventType, fn, false);
    }
};

или

Object.prototype.bind = function(eventType, fn) {
    if (this instanceof Element) {
        this.addEventListener(eventType, fn, false);
    } else if (this instanceof NodeList) {
        for (var i = 0, l = this.length; i < l; i++) {
            this[i].addEventListener(eventType, fn, false);
        }
    }
}

1 Ответ

3 голосов
/ 29 сентября 2011

Большой красный флаг: никогда расширить Object.prototype! Это ломает for (x in y) (или, по крайней мере, ожидания людей о том, как это работает).

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

Во-первых, JavaScript - это язык с динамической типизацией, поэтому вы, как правило, предпочитаете утиную типизацию и базовое наследование, а не instanceof и рефлексию. Во многих случаях производительность невелика, но в основном это так, что вы не тратите время на борьбу с языком.

Во-вторых, этот тип переключения методов подразумевает соединения между коммутируемыми методами, которые не обязательно существуют. В вашем примере кода это можно увидеть в версии NodeList. Концептуально список не должен связывать ничего; если у него есть метод bind, он должен просто переводить вызов метода bind для каждого из его элементов. Это гарантирует, что если в будущем потребуется добавить какие-либо дополнительные шаги для привязки (скажем, обходные пути для старых, не соответствующих DOM-браузерам…), вам нужно будет сделать это только в одном месте.

Но если посмотреть на это с точки зрения переключения типов в «одной и той же функции», создается ложное впечатление, что и Element.bind, и NodeList.bind должны работать одинаково - вызывая addEventListener. Вот как я бы это реализовал:

Element.prototype.bind = function(eventType, fn) {
    this.addEventListener(eventType, fn, false);
};

NodeList.prototype.bind = function(eventType, fn) {
    for (var i = 0, l = this.length; i < l; i++) {
        this[i].bind(eventType, fn);
    }
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...