В настоящее время я перехожу из Java в Javascript, и мне немного сложно понять, как расширять объекты так, как я хочу.
Я видел, как несколько человек в интернете использовали метод, называемый extends для объекта. Код будет выглядеть так:
var Person = {
name : 'Blank',
age : 22
}
var Robot = Person.extend({
name : 'Robo',
age : 4
)}
var robot = new Robot();
alert(robot.name); //Should return 'Robo'
Кто-нибудь знает, как заставить это работать? Я слышал, что вам нужно написать
Object.prototype.extend = function(...);
Но я не знаю, как заставить эту систему работать. Если это невозможно, пожалуйста, покажите мне другую альтернативу, которая расширяет объект.
extend
функции, я привелОтветы:
Вы хотите «наследовать» от объекта-прототипа Person:
источник
Person()
конструкторnew Robot()
? Мне кажется, что вы должны вызывать этот конструктор базового класса, а не делать этоthis.name = name;
вRobot()
конструкторе ...Person.apply(this, arguments);
. Также было бы лучше использоватьRobot.prototype = Object.create(Person.prototype);
вместоnew Person();
.Мир без «нового» ключевого слова.
И более простой «прозаоподобный» синтаксис с Object.create ().
* Этот пример обновлен для классов ES6.
Прежде всего, помните, что Javascript - это прототип языка . Это не на основе класса. Следовательно, письмо в прототипной форме раскрывает его истинную природу и может быть очень простым, подобным прозе и мощным.
TLDR;
Нет, вам не нужны конструкторы, не нужно создавать
new
экземпляры ( читайте, почему вы не должны их использоватьnew
), нетsuper
, не смешно, смешно__construct
. Вы просто создаете объекты, а затем расширяете или изменяете их.( Если вы знаете о методах получения и установки, обратитесь к разделу «Дальнейшее чтение», чтобы узнать, как этот шаблон дает вам бесплатные методы получения и установки, как Javascript изначально предназначался, и насколько они мощны .)
Прозе-подобный синтаксис: Базовый прототип
На первый взгляд выглядит очень читабельно.
Расширение, создающее потомка
Person
* Правильные условия есть
prototypes
, и ихdescendants
. Нетclasses
и не нужноinstances
.Один из способов обеспечить «по умолчанию» способ создания
descendant
, это присоединение#create
метода:Способы ниже имеют более низкую читаемость:
Сравните с «классическим» эквивалентом:
Читаемость кода с использованием «классического» стиля не так хороша.
ES6 Классы
Следует признать, что некоторые из этих проблем устранены классами ES6, но все же:
Разветвление базового прототипа
Прикрепите методы, уникальные для
Robot
Проверка наследования
У вас уже есть все, что вам нужно! Нет конструкторов, нет экземпляров. Чистая, ясная проза.
дальнейшее чтение
Пишемость, конфигурируемость и бесплатные геттеры и сеттеры!
Для свободных методов получения и установки или для дополнительной настройки вы можете использовать второй аргумент Object.create () aka propertiesObject. Он также доступен в # Object.defineProperty и # Object.defineProperties .
Чтобы проиллюстрировать, насколько это мощно, предположим, что мы хотим, чтобы все
Robot
были строго сделаны из металла (черезwritable: false
), и стандартизировалиpowerConsumption
значения (через геттеры и сеттеры).И все прототипы
Robot
не могут бытьmadeOf
чем-то еще потому чтоwritable: false
.Миксины (используя # Object.assign) - Анакин Скайуокер
Вы чувствуете, куда это идет ...?
Дарт Вейдер получает методы
Robot
:Наряду с другими странными вещами:
Что ж, Дарт Вейдер - человек или машина, действительно субъективен:
Extra - немного более короткий синтаксис с # Object.assign
По всей вероятности, этот шаблон сокращает ваш синтаксис. Но ES6 # Object.assign может укоротить еще немного (о том, как polyfill использовать в старых браузерах, см. MDN на ES6 ).
источник
Object.assign(Robot, {a:1}
хорошей альтернативой для вашегоextend()
метода? 2) Как переопределитьgreet()
метод, чтобы он возвращал тот же текст, но с добавлением «greet override»?#Object.assign
выглядит как хорошая альтернатива. Но поддержка браузера ниже. 2) Вы будете использовать__proto__
свойство объекта для доступа к функции приветствия его прототипа. затем вы вызываете функцию приветствия прототипа с переданной областью действия вызываемого. В этом случае функция была консольным журналом, поэтому «добавить» невозможно. Но с этим примером я думаю, что вы получите дрейф.skywalker.greet = function() { this.__proto__.greet.call(this); console.log('a greet override'); }
Если вы еще не нашли способ, используйте ассоциативное свойство объектов JavaScript, чтобы добавить функцию расширения к
Object.prototype
как показано ниже.Затем вы можете использовать эту функцию, как показано ниже.
источник
Другой подход: Object.create
В ответе @osahyoun я нахожу следующее как лучший и эффективный способ «наследования» от объекта-прототипа Person:
Создайте новые экземпляры:
Теперь с помощью Object.create :
Проверьте также документацию MDN .
источник
name
параметр родительскому конструктору, например: jsfiddle.net/3brm0a7a/3 (разница в строке № 8)В ES6 вы можете использовать оператор распространения, как
Для получения дополнительной информации см. Ссылку, MDN-Распространенный синтаксис
Старый ответ:
В ES6 есть
Object.assign
для копирования значений свойств. Используйте в{}
качестве первого параметра, если вы не хотите изменять целевой объект (первый пройденный параметр).Для более подробной информации смотрите ссылку, MDN - Object.assign ()
Если вам нужен Polyfill для ES5 , ссылка тоже его предлагает. :)
источник
И еще год спустя, я могу сказать вам, что есть еще один хороший ответ.
Если вам не нравится, как работает прототипирование для расширения объектов / классов, взгляните на это: https://github.com/haroldiedema/joii
Краткий пример кода возможностей (и многих других):
источник
Людей, которые все еще борются за простой и лучший подход, можно использовать
Spread Syntax
для расширения объекта.Примечание. Помните, что свойство, наиболее удаленное справа, будет иметь приоритет. В этом примере
person2
находится справа, поэтому в немnewObj
будет имя Robo .источник
Возможно, вы захотите использовать вспомогательную библиотеку, например underscore.js , которая имеет собственную реализацию
extend()
.И это также хороший способ учиться, глядя на его исходный код. Аннотированный исходный код страницы является весьма полезным.
источник
_.extend()
делают его функционал достаточно ясным: lostechies.com/chrismissal/2012/10/05/…Mozilla «объявляет» объект, выходящий из ECMAScript 6.0:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/extends
ПРИМЕЧАНИЕ. Это экспериментальная технология, являющаяся частью предложения ECMAScript 6 (Harmony).
Эта технология доступна в Gecko (Google Chrome / Firefox) - ночные сборки 03/2015.
источник
В большинстве проектов есть некоторые реализации объекта расширения: подчеркивание, JQuery, lodash: продлить .
Существует также чистая реализация javascript, которая является частью ECMAscript 6: Object.assign : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
источник
Затем:
Обновление 01/2017:
Пожалуйста, игнорируйте мой ответ 2015 года, так как Javascript теперь поддерживает
extends
ключевое слово начиная с ES6 (Ecmasctipt6)- ES6:
- ES7:
источник
new ParentClass()
перед перезаписью конструктора, вы уже выполнили родительский конструктор. Я не думаю, что это правильное поведение, если вы спросите меня ...Резюме:
Javascript использует механизм, который называется наследование прототипов . Прототип наследования используется при поиске свойства объекта. Когда мы расширяем свойства в javascript, мы наследуем эти свойства от реального объекта. Это работает следующим образом:
myObj.foo
илиmyObj['foo']
), механизм JS сначала ищет это свойство в самом объекте.Когда мы хотим расшириться от объекта в javascript, мы можем просто связать этот объект в цепочке прототипов. Есть множество способов добиться этого, я опишу 2 наиболее часто используемых метода.
Примеры:
1.
Object.create()
Object.create()
это функция, которая принимает объект в качестве аргумента и создает новый объект. Объект, который был передан в качестве аргумента, будет прототипом вновь создаваемого объекта. Например:2. Явная установка свойства prototype
При создании объектов с использованием функций конструктора мы можем установить свойства add для его свойства объекта prototype. Созданные объекты формируют функцию конструктора при использовании
new
ключевого слова, их прототип установлен на прототип функции конструктора. Например:источник
Вы можете просто сделать это, используя:
Тогда используйте это как:
Это хорошо приводит к:
источник
ПОЖАЛУЙСТА, ДОБАВЬТЕ ПРИЧИНУ ДЛЯ СКАЧИВАНИЯ
Нет необходимости использовать какую-либо внешнюю библиотеку для расширения
В JavaScript все является объектом (за исключением трех примитивных типов данных, и даже они автоматически оборачиваются объектами при необходимости). Кроме того, все объекты являются изменяемыми.
благодаря Россу Хармсу, Дастину Диасу
источник
Это позволит расширить ваши свойства и создать новый объект с прототипами параметров объекта без изменения переданного объекта.
Но если вы хотите расширить свой объект без изменения его параметров, вы можете добавить exteProperty к своему объекту.
источник
Прототипирование - хороший способ, но иногда прототип довольно опасен и может привести к ошибкам. Я предпочитаю инкапсулировать это в базовый объект, как это делает Ember.js для Ember.Object.extend и Ember.Object.reopen. Это гораздо безопаснее в использовании.
Я создал суть того, как вы настроите нечто похожее на то, что использует Ember.Object.
Вот ссылка: https://gist.github.com/WebCloud/cbfe2d848c80d4b9e9bd
источник
Prototyping is a nice way, but prototype is quite dangerous sometimes and can lead to bugs.
Что ты имеешь в виду? Использование цепочки прототипов в JavaScript может привести к ошибкам? Это все равно что сказать, что использование классов на Java может привести к ошибкам и не имеет никакого смысла.Object
прототип, ваша функция может иметь то же имя, что и будущая функция JavaScript, и заставить ваш код взорваться при запуске в будущем. Например, скажем, вы добавилиrepeat()
функциюObject
и вызвали ее вString
экземплярах, а затем ваша среда выполнения JavaScript обновилась до ES6?prototype
языковой функцией .