Как сделать цепной интерфейс, используя функции конструктора в Javascript?

Я хочу цепной интерфейс, похожий на jQuery. Тем не менее, все учебные пособия по прототипам, доклады, исходные коды jQuery не проясняют этого, поэтому очень ценю помощь в решении этой проблемы.

В jQuery я могу вызывать jQuery('. Apple'), но также jQuery.ajax('param'), так как jQuery кажется функцией конструктора и, следовательно, может иметь свойства, такие как предполагаемая функция ajax?

Что я хочу:

Postal('apple') // Return chain-able function/object/constructor thing
Postal('apple').send('China').fee(99) // Used like this 

Postal.send // should be undefined, need product-selector
Postal.area // should be function, accepting 1 parameter

Postal.area('Europe') // Use like this
Postal.area('Asia')

Примечание выше: область должна быть доступна для цепных методов, таких как send()

Функции, которые могут использовать селектор продукта "Global Accessor":

Postal('apple').send('China').fee(9) // Apples to China fee
Postal('apple').fee(9) // Apples to anywhere default fee
Postal('orange').send('USA').fee(9) 

Моя попытка решить это:

Комментарии касаются моего подхода к пониманию и подражанию источнику jQuery:

// # Assume
// ES2016 and not to much performance downsides or object allocations

//This should become our Globalisk-jQuery-Accessor
var Postal

// Create a non-global scope inside here
(function() {

    // Locals that are global for the postal-object-function
    var p_area           = 'global'
    var p_destination    = 'unknown'
    var p_product        = '<unknown product>'

    // our main selector, like: jQuery('.container')
    var postal = (product) => {
        // We use the same postal-object but create a new instance that can
        // handle initializations of something
        return new postal.prototype.init(product)
    }

    // All functions that only callable with a product-selector
    postal.prototype = {
        init: (product) => {
            console.log("Init ran "+product)
            // here we return this in case of no arguments?
            // should we return the base object with slightly different methods?
            if (!arguments[0]) {
                return this
            }

            // Make 'product' parameter local to this postal call but shared
            // amongst all chaining functions
            p_product = product // or?
        }
    }

    area = (area) => {
        p_area = area //Save for future calls
        console.log("Area set to: " + area)
        return
        // No return since no chaining possible after area is set
    }

    send = (destination) => {
        p_destination = destination //Save for future chaining
        console.log("Sending to " + destination + "...")
        return send
    }

    send.fee = function fee(amount) {
        console.log("Setting "+p_destination+" send fee to " + amount + " in " +
        p_area + " for product "+ p_product)
        return fee
    }

    // Set so new instance has same "properties" as postal has itself
    //Need something like this? postal.prototype.init.prototype = postal.prototype

    Postal = postal // Set our global accessor, from now on it should be const

})()

// Call direct function without going trough selector
console.log( Postal.send === undefined )

Postal.area('Europe') // Change the Postal-global "current area" state
Postal('apple').send('China').fee(99) // Applies only to "Europe"
Postal.area('Asia')
Postal('apple').send('China').fee(33)
Postal('orange').send('USA').fee(9)

Ожидаемый результат:

Предполагая, что код исправлен, чтобы работать как задумано. Я работаю в узле v5.3.0.

true
Area set to: Europe
init ran apple
Sending to China...
Setting China send fee to 99 in Europe for product apple
Area set to: Asia
Sending to China...
Setting China send fee to 33 in Asia for product apple
init ran orange
Sending to USA...
Setting USA send fee to 9 in Asia for product orange

Это легко сделать с помощью двух методов доступа, таких как: PostalCore.area() для global-методов и Postal("продукт здесь") для методов выбора продуктов, поэтому суть вопроса заключается в том, как это сделать с помощью конструктора. функция, так что можно иметь оба на одном объекте, как это делает jQuery - я также приветствую аргументы почему бы и нет:)

0 ответов

Другие вопросы по тегам