#javascript #arrays #function #object #methods
#javascript #массивы #функция #объект #методы
Вопрос:
У меня есть функция, предназначенная для использования с new
конструктором. Он должен возвращать массив со значением ["Hello World"]
и включать функции в качестве методов. Вот пример / демонстрация (извините, если это немного некрасиво):
var my_object = function () {
this.foo = function (data) { // alert and add new item
alert(data);
this.push(data);
};
this.bar = function () { // alert and remove last item
alert(this.pop());
};
this.baz = function (stuff) { // replace last item by running previous methods
this.bar();
this.foo(stuff);
};
var a = "Hello World";
return [a];
};
var arr = new my_object(); // ["Hello World"]
Как и ожидалось, arr имеет значение ["Hello World"]
. Однако следующий код выдает ошибку:
arr.foo('some-text'); // "TypeError: arr.foo is not a function"
Тот же тип ошибки появляется с двумя другими функциями. Что я могу сделать, чтобы это работало, без изменения Array.prototype, создания методов вне функции или удаления возможности инициализации с помощью new my_object()
?
Примечание: По возможности, пожалуйста, не включайте ответы с использованием jQuery или других внешних библиотек.
Комментарии:
1.
this
это не то значение, которое вы возвращаете из функции, поэтому любой из объявленных вами методов отбрасывается и не используется.2. Поскольку вы возвращаете массив, .. у массивов нет методов с именем ‘foo’
3. итак, вы хотите наследовать от массива и добавлять новые методы?
4. Какая дизайнерская идея стоит за этим?
Arrays
являются типами . Вы используете функцию с объектно-ориентированным подходом, но восстанавливаете из нее массив.5. Это может помочь OP -> github.com/wesbos/es6-articles/blob/master /…
Ответ №1:
Как упоминалось в комментариях, эта ссылка содержит некоторую ценную информацию -> https://github.com/wesbos/es6-articles/blob/master/54 — Extending Arrays with Classes for Custom Collections.md
Используя это, ваш код может быть изменен следующим образом,. ->
Конечно, это так ES6
, расширение массивов было невозможно в ES5
дни..
В Chrome instanceof
при отображении работает так, как ожидалось, но не уверен, что перенесенный код работал бы здесь, если бы это было обязательным требованием. Например, если вы нажмете использовать предустановку Babel в этом фрагменте, вы увидите, что он не работает, поэтому, если вы хотите, чтобы это работало в старых браузерах, даже если они были перенесены, это может быть проблемой.
class my_object extends Array {
foo(data) {
alert(data);
this.push(data);
}
bar() {
alert(this.pop());
}
baz(stuff) {
this.bar();
this.foo(stuff);
}
constructor () {
super("Hello World");
}
};
var arr = new my_object(); // ["Hello World"]
arr.foo("some-text");
console.log(arr);
Комментарии:
1. Это может работать даже лучше, чем предыдущий ответ (т.Е. меньше изменений в моем коде). Спасибо!
Ответ №2:
Если вы не используете какой-либо Babel или что-то еще, что может обеспечить безопасность вашего кода, так это использование наследования и цепочки прототипов. JavaScript defaults не является объектно-ориентированным программированием, но претендует на ООП.
В вашем случае при построении вы возвращаете, ["Hello World"]
который является массивом, а не экземпляром my_object. Вы можете вернуть this вместо [a].
Кроме того, у вас нет ни одного массива, на который вы могли бы ссылаться. Вы работаете с локальным объектом, когда используете это, и у вас есть, вероятно TypeError: this.push is not a function
.
Я улучшил ваш случай. Посмотрите, что такое return, где я использую это и ссылку на массив данных.
Приветствую, слива!
Улучшенный код:
var my_object = function () {
this.data = [];
this.foo = function (data) { // alert and add new item
alert(data);
this.data.push(data);
};
this.bar = function () { // alert and remove last item
alert(this.data.pop());
};
this.baz = function (stuff) { // replace last item by running previous methods
this.bar();
this.foo(stuff);
};
var a = "Hello World";
return this;
};
var arr = new my_object(); // [object Object] - a my_object instance
console.log(arr)
arr.foo('some-text');
Комментарии:
1. Ваше решение должно быть размещено здесь, а не на внешнем сайте. Кроме того, это не работает — он возвращает объект , а не массив.
2. Спасибо! С моей стороны потребуется немного редактирования для работы с остальной частью моего кода, но он будет работать отлично.
3. @VLAZ Я отредактировал свой ответ, я буду помнить об этом в будущем. Вы не можете возвращать массив и работать с методами экземпляра. Или вы возвращаете массив или объект, но какой смысл возвращать массив из конструктора?
4. @plumthedev вы могли бы вернуть массив. Точнее, подкласс массива. Или вы также могли бы просто сделать
return []
но тогда функция конструктора — странный выбор. Во всяком случае, я исходил из того, что OP выразил в вопросе, где было желаниеarr
буквально быть массивом. OP никогда не отвечал на комментарии, чтобы указать, должен ли это быть буквальный массив, подкласс array, массивоподобный или … по-видимому, вообще не массив, поскольку это выбранное решение.