Как создать функцию-оболочку $ (), подобную jquery?

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

arrayFunction( [1, 2, 3] ).someSpecialArrayFunction();

Таким образом, оставляя обычный объект массива неизменным. Поэтому я придумал следующую конструкцию (вдохновленную исходным кодом jQuery):

var arrayFunction = window.arrayFunction = function(array) {
    return new arrayFunction.fn.init(array);
}
arrayFunction.fn = arrayFunction.prototype = {
    init: function(array){
        this.a = array;
        //should I return something here?
    },
    someSpecialArrayFunction: function(){
        //Super cool custom stuff here.
    }
}

Однако это не работает (очевидно). Что должно произойти в функции init ()?

Ошибка сейчас в том, что когда я пытаюсь:

 arrayFunction(array).someSpecialArrayFunction();

там написано, что someSpecialArrayFunction () не является функцией?

Как это сделать?

редактировать
Да, это действительно упрощенный пример. На самом деле методов гораздо больше.

Кроме того, я просто подумал о том, как было бы здорово, если бы он также поддерживал ченинг, как бы вы это сделали?

$ For jquery на самом деле является объектом.

Malfist 08.01.2009 20:57

В Javascript все функции являются объектами - вы фактически объявляете объекты с помощью ключевого слова function, поэтому jQuery $ является одновременно объектом и функцией, возвращающей экземпляры этого объекта. К этому нужно привыкнуть ...

Dylan Beattie 08.01.2009 21:21

Вы ищете здесь способ сделать свой пример Работа - или общий шаблон для добавления методов к объекту оболочки, добавляя их к прототипу оболочки, например чтобы вы могли управлять большими коллекциями методов расширения?

Dylan Beattie 08.01.2009 21:47
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
3
1 133
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

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

var arrayFunction = window.arrayFunction = function(array) {
    return new arrayFunction.fn.init(array);
}
arrayFunction.fn = arrayFunction.prototype = {
    init: function(array){
        var a = array;
        return  {
            someSpecialArrayFunction: function(){
                alert (a.join(' - ') ); //Super cool custom stuff here.
            }
        };
    },
}
arrayFunction( [1, 2, 3] ).someSpecialArrayFunction();
Ответ принят как подходящий

Или просто:

var arrayFunction = function(array) {
    var someSpecialArrayFunction = function() {
        // do something with array
    };
    return {
        someSpecialArrayFunction: someSpecialArrayFunction
    }
};
arrayFunction( [1, 2, 3] ).someSpecialArrayFunction();

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

Вам следует откатить редактирование: это не сработает! Переменная массива в вашем закрытии всегда будет привязана к массиву, переданному в качестве аргумента для первого вызова myArrayFunction () ...

Christoph 09.01.2009 00:22

отвечатьSktrdie выглядит неплохо.

Еще одна вещь, которую следует учитывать, - это использовать модель наилегчайшего веса вместо возврата нового экземпляра объекта при каждом вызове вашей оболочки. Это делает функция ExtJS Ext.fly; он возвращает глобально разделяемый экземпляр.

Попробуйте что-то вроде этого:

var mathWrapper = function(array) {
    return {
        mean : function(){
            if (array.length == 0) return(0);
            var total = 0;
            for (var i = 0; i < array.length; i++) total += array[i];
            return(total / array.length);
        },
    };
}

Вызов его через что-то вроде

document.write(mathWrapper([1,2,3,4,5,6]).mean());

должен возвращать среднее значение элементов массива.

Это неэффективно с точки зрения памяти - используйте объект-оболочку и вместо этого добавьте методы в его прототип ...

Christoph 09.01.2009 00:28

@Christoph - а ... внезапно множество вещей, которые меня сбивали с толку, обретают смысл! Спасибо.

Dylan Beattie 09.01.2009 00:46

Если вы не хотите менять Array.prototype, единственное реально возможное решение - добавить методы к конкретному объекту массива:

function doSomething() {}
function doOther() {}

function wrap(array) {
    array.doSomething = doSomething;
    array.doOther = doOther;
    return array;
}

Обратите внимание, что я не определяю doSomething() и doOther() в wrap() - в противном случае мы бы создавали новые объекты функций при каждом вызове, что крайне неэффективно.

Более сложный вариант будет следующим:

function doSomething() {}
function doOther() {}

function wrap(array) {
    if (this instanceof arguments.callee) {
        this.doSomething = doSomething;
        this.doOther = doOther;
    }
    else {
        arguments.callee.prototype = array;
        return new arguments.callee;
    }
}

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

var foo = wrap([1,2,3]);
document.writeln(foo.length); // writes 3
foo.push(4);
document.writeln(foo.length); // writes 4 in FF, 3 in IE
foo[4] = 5;
foo[5] = 6;
document.writeln(foo.length); // still writes 4?!

Использование foo[4] = приведет к доступу к нашему объекту-оболочке, и свойства 4 и 5 будут установлены там, а не в массиве, поэтому его свойство длины не будет обновлено. В IE вызов push() уже не сможет правильно обновить массив ...

Если вашему объекту-оболочке не нужно «перенаправлять» вызовы объекта массива, существуют другие решения, использующие замыкания - первый пример sktrdie является одним из них. Я бы возражал против них, потому что они также будут создавать новые объекты функций при каждом вызове. Что бы я сделал:

function wrap(array) {
    if (this instanceof arguments.callee)
        this.array = array;
    else return new arguments.callee(array);
}

wrap.prototype.doSomething = function() {};
wrap.prototype.doOther = function() {};

Здесь вы можете получить доступ к массиву в doSomething() и doOther() через this.array.

Просто расширьте объект Array и добавьте к своему объекту свои причудливые методы. Затем вы можете создать функцию моста, которая принимает массив в качестве аргумента и возвращает вашу версию массива. Этот метод намного проще и полезнее.

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