Примеры имеют очень разные результаты.
Перед рассмотрением различий следует отметить следующее:
[[Prototype]]
экземпляра. myObj.method()
), то этот внутри метода ссылается на объект. Где этот не задан вызовом или с помощью bind , он по умолчанию ссылается на глобальный объект (окно в браузере) или в строгом режиме, остается неопределенным. Итак, вот фрагменты, о которых идет речь:
var A = function () {
this.x = function () {
//do something
};
};
В этом случае переменной A
присваивается значение, которое является ссылкой на функцию. Когда эта функция вызывается с помощью A()
, функция этой функции не задается вызовом, поэтому по умолчанию используется глобальный объект, и выражение this.x
эффективно window.x
. В результате ссылка на выражение функции с правой стороны назначается window.x
.
В случае:
var A = function () { };
A.prototype.x = function () {
//do something
};
происходит нечто совсем другое. В первой строке переменной A
присваивается ссылка на функцию. В JavaScript все объекты функций имеют свойство prototype по умолчанию, поэтому нет никакого отдельного кода для создания объекта A.prototype .
Во втором line, A.prototype.x назначается ссылка на функцию. Это создаст свойство x , если оно не существует, или назначьте новое значение, если это произойдет. Таким образом, разница с первым примером заключается в том, какое свойство объекта x участвует в выражении.
Другой пример приведен ниже. Это похоже на первое (и может быть то, о чем вы хотели спросить):
var A = new function () {
this.x = function () {
//do something
};
};
В этом примере оператор new
был добавлен перед выражением функции, чтобы вызвать функцию как конструктор. При вызове с new
функция этой функции установлена для ссылки на новый объект, чье личное свойство [[Prototype]]
установлено для ссылки на общедоступный прототип конструктора . Поэтому в операторе присваивания свойство x
будет создано на этом новом объекте. Когда вызывается как конструктор, функция по умолчанию возвращает свой этот объект , поэтому нет необходимости в отдельном заявлении return this;
.
Чтобы проверить, что A имеет свойство x :
console.log(A.x) // function () {
// //do something
// };
Это необычное использование new , так как единственный способ ссылки на конструктор - через A.constructor . Это было бы гораздо чаще:
var A = function () {
this.x = function () {
//do something
};
};
var a = new A();
Другой способ достижения аналогичного результата - использовать сразу вызываемое выражение функции:
var A = (function () {
this.x = function () {
//do something
};
}());
В этом случае A
присвоено возвращаемое значение вызова функции с правой стороны. Здесь опять же, поскольку этот не задан в вызове, он будет ссылаться на глобальный объект, а this.x
- эффективно window.x
. Поскольку функция ничего не возвращает, A
будет иметь значение undefined
.
Эти различия между этими двумя подходами также проявляются, если вы сериализуете и де-сериализуете свои объекты Javascript в / от JSON. Методы, определенные на прототипе объекта, не сериализуются при сериализации объекта, что может быть удобно, если, например, вы хотите сериализовать только части данных объекта, но не его методы:
var A = function () {
this.objectsOwnProperties = "are serialized";
};
A.prototype.prototypeProperties = "are NOT serialized";
var instance = new A();
console.log(instance.prototypeProperties); // "are NOT serialized"
console.log(JSON.stringify(instance));
// {"objectsOwnProperties":"are serialized"}
Связанные Вопросы:
Sidenote: не может быть значительной экономии памяти между двумя подходами, однако использование прототипа для совместного использования методов и свойств, скорее всего, будет использовать меньше памяти, чем каждый экземпляр имея свою собственную копию.
JavaScript не является языком низкого уровня. Возможно, не очень важно думать о прототипировании или других шаблонах наследования как способ явного изменения способа выделения памяти.
Первое, что пришло на ум:
Только первые два объекта действительно уникальны для функциональных языков (т.е. почти все императивные языки нетерпеливы и нечисты).
Существует много различий, но только два различия я категоризировал бы как фундаментального в этом, они имеют большое значение к Вашей разработке:
Функциональное программирование является стилем, не конструкцией языка
, самые функциональные языки имеют некоторые общие принципы:
, Но самый важный принцип состоят в том, что они обычно вынуждают Вас записать в функциональном стиле. Можно программировать в функциональном стиле на большей части любого языка. C# можно было считать "функциональным" при написании кода как этот как мог любой другой язык.
Мне нравится ответ Chris Conway, который указывает некоторые важные оси, что справка классифицирует различные функциональные языки.
С точки зрения функций определенных языков, я выберу F# для вызова некоторых функций, не найденных во многих других FPLs:
С точки зрения общей классификации, F#
, Ваш вопрос формулируется способом с ясной предвзятостью против некоторой прагматики дополнительного языка (например, что делает время выполнения она интегрируется с), но Вы также спрашиваете, что "влияет на способ, которым Вы разрабатываете", и эти вещи действительно влияют на это:
(я думаю, что попытка разделить язык от его времени выполнения и инструментов является главным образом академическим осуществлением.)
, Таким образом, существует описание партии отличительных особенностей одного конкретного языка, которого я - поклонник. Я надеюсь, что другие могли бы отправить подобные ответы, которые вызывают отличительные особенности других отдельных языков.
Когда Вы говорите, что код как данные, которые Вы отсылаете к языку, где код представлен в структуре данных. Это упоминается как Homoiconicity и это обычно только верно для языков, которые являются диалектами шепелявости или чем-то близко к нему. Haskell, Erlang и Scala не являются Гомографическими, Clojure.
фундаментальные дифференциаторы Clojure:
Это имеет программное обеспечение Транзакционная Система памяти, которая делает общее состояние параллельным программирующий легче
, Это - Lisp, в отличие от Haskell или Erlang, поэтому весь код является данными, которые позволяют Вам делать, какому взгляду нравятся изменения в самом языке во времени выполнения через макро-систему
, Это работает на JVM, что означает, что у Вас есть прямой доступ ко всем библиотекам Java
, структуры данных Clojure реализуют интерфейсы Java, такие как Набор, Список, Карта, Выполнимая и Вызываемая в соответствующих случаях. Строками являются просто Строки Java, Числами являются Целые числа Java, и Удваивается. Это означает, что структуры данных Clojure могут быть переданы непосредственно библиотекам Java без любого образования моста или перевода
Фундаментальные свойства?
первое красиво, вторым является ужасный побочный эффект первого (предназначенная игра слов).
реальная компенсация из-за отсутствия - то, что я нахожу, чтобы быть самым большим дифференциатором между функциональными языками.
Те немного вещей дают много бесплатных наборов. Большую часть времени языки обрабатывают memoization.
Нестрогие и строгие вычисления.
Статическая и динамическая типизация.
Структурная и номинальная статическая типизация. OCaml - единственный язык, на котором я могу подумайте о структурной типизации (как в объектах, так и в полиморфных вариантах), который закрывает пробел динамическими печатая, убрав необходимость определить много типов (например, вариант типы).
Производные Хиндли-Милнера и другие алгоритмы вывода статических типов. SML, OCaml, Haskell и F # используют алгоритмы вывода типов, основанные на Хиндли-Милнера, тогда как Scala имеет только вывод локальных типов (например, C # 3) и требует для компиляции гораздо большего количества аннотаций. (Код Haskell часто полон аннотаций типов на уровне функций, но большинство из них не нужны и добавляются для документации и помощи компилятору при наличии ошибок).
Сопоставление с образцом и руководство деконструкция. SML, OCaml, F #, Haskell, Mathematica и Scheme автоматизировать деконструкцию значения.
Типы закрытой суммы и только типы открытой суммы. SML, OCaml, F # и Haskell позволяют определять закрытые / запечатанные алгебраические типы для усиления статической типизации за счет неявной передачи более конкретных ограничений. OCaml и F # также допускают открытые типы сумм, тогда как SML - нет, а Haskell требует сложного обходного пути (описанного Олегом Киселевым).
Шаблоны с ограниченным временем. Сопоставление с образцом выполняется очень быстро в SML и (ванильном) OCaml, но имеет неизвестную производительность в F # из-за активных шаблонов и даже неизвестной асимптотической сложности в Mathematica.
Компиляция на лету в родной код. F #, Lisp и Scheme разрешают код быть сгенерированным, скомпилированным и эффективно выполняется во время выполнения.
Макросы. OCaml, Mathematica, Lisp и Scheme - это расширяемые языки.
Стандартизированные и проприетарные. SML, Haskell 2010, Common Lisp и Scheme являются стандартизованными языками, тогда как OCaml, Erlang, F # и Mathematica являются проприетарными.