JavaScript продолжает удивлять меня, и это еще один пример. Я только что наткнулся на код, который сначала не понял. Поэтому я отладил его и пришел к такому выводу:
alert('a'['toUpperCase']()); //alerts 'A'
Теперь это должно быть очевидно, если toUpperCase()
оно определено как член строкового типа, но изначально оно не имело смысла для меня.
Тем не мение,
- это работает, потому что
toUpperCase
является членом «а»? Или что-то еще происходит за кулисами? код я читал имеет функцию следующим образом :
function callMethod(method) { return function (obj) { return obj[method](); //**how can I be sure method will always be a member of obj** } } var caps2 = map(['a', 'b', 'c'], callMethod('toUpperCase')); // ['A','B','C'] // ignoring details of map() function which essentially calls methods on every // element of the array and forms another array of result and returns it
Это своего рода общая функция для вызова ЛЮБЫХ методов для ЛЮБОГО объекта. Но значит ли это, что указанный метод уже будет неявным членом указанного объекта?
Я уверен, что мне не хватает серьезного понимания основной концепции функций JavaScript. Пожалуйста, помогите мне понять это.
javascript
function
Mahesha999
источник
источник
arr[5]
. Если числа , где действительные имена идентификаторов можно использовать точечную нотацию:arr.5
.5['toString']()
.Ответы:
Чтобы сломать это.
.toUpperCase()
это методString.prototype
'a'
является примитивным значением, но преобразуется в его объектное представлениеТак
является доступ через обозначение скобки на имущество
toUpperCase
, сString.prototype
. Поскольку это свойство ссылается на метод , мы можем вызвать его, прикрепив()
источник
foo.bar
иfoo['bar']
равны, поэтому код, который вы разместили, такой же, какПри использовании
foo[bar]
(обратите внимание на отсутствие кавычек) вы используете не буквальное имя,bar
а любое значение, котороеbar
содержит переменная . Таким образом, использованиеfoo[]
обозначения вместоfoo.
позволяет использовать динамическое имя свойства.Давайте посмотрим на
callMethod
:Прежде всего, он возвращает функцию, которая принимает в
obj
качестве аргумента. Когда эта функция выполняется, она вызываетmethod
этот объект. Таким образом, данный метод просто должен существовать либоobj
сам по себе, либо где-то в своей цепочке прототипов.В случае, если
toUpperCase
этот метод происходитString.prototype.toUpperCase
- было бы довольно глупо иметь отдельную копию метода для каждой существующей строки.источник
Вы можете получить доступ к членам любого объекта с помощью
.propertyName
нотации или["propertyName"]
нотации. Это особенность языка JavaScript. Чтобы убедиться, что член находится в объекте, просто проверьте, определен ли он:источник
По сути, javascript рассматривает все как объект, точнее, каждый объект можно рассматривать как словарь / ассоциативный массив. И функции / методы определяются точно так же для объекта - как запись в этом ассоциативном массиве.
По сути, вы ссылаетесь / вызываете (обратите внимание на ' () ') свойство 'toUpperCase' объекта 'a' (в данном случае это строковый тип).
Вот некоторый код верхней части моей головы:
источник
anyObject['anyPropertyName']
так же, какanyObject.anyPropertyName
когдаanyPropertyName
нет проблемных символов.См. Работа с объектами из MDN.
toUpperCase
Метод прикреплен к типу String. Когда вы вызываете функцию для примитивного значения, здесь'a'
оно автоматически превращается в объект, здесь String :Вы можете увидеть, что функция существует, войдя в систему
String.prototype.toUpperCase
.источник
Так в Javascript,
objects
естьobjects
. То есть они такой природы{}
. Свойства объекта могут быть установлены с помощью одного из следующих:a.greeting = 'hello';
илиa['greeting'] = 'hello';
. Оба способа работают.Поиск работает так же.
a.greeting
(без кавычек) есть'hello'
,a['greeting']
есть'hello'
. Исключение: если свойство является числом, работает только метод скобок. Точечный метод этого не делает.Так
'a'
же как и объект со'toUpperCase'
свойством, которое на самом деле является функцией. Вы можете извлечь функцию и впоследствии вызвать ее любым способом:'a'.toUpperCase()
или'a'['toUpperCase']()
.Но, по моему мнению, лучший способ написать функцию карты был бы таков:
var caps = ['a','b','c'].map( function(char) { return char.toUpperCase(); } )
кому тогда нужна
callMethod
функция?источник
Каждый объект JavaScript является хеш-таблицей, поэтому вы можете получить доступ к его членам, указав ключ. например, если переменная является строкой, то она должна иметь функцию toUpperCase. Таким образом, вы можете вызвать его
так, по встроенной ул, вы могли бы иметь ниже
источник
toUpperCase - это стандартный метод javascript: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/String/toUpperCase
Причина, по которой он работает так,
'a'['toUpperCase']()
заключается в том, что функция toUpperCase является свойством строкового объекта'a'
. Вы можете ссылаться на свойства объекта с помощьюobject[property]
илиobject.property
. Синтаксис 'a''toUpperCase' указывает, что вы ссылаетесь на свойство 'toUppercase' строкового объекта 'a', а затем вызываете его ().источник
Кто-то может передать объект, который
toUpperCase
; илиtoUpperCase
, которое не является функциейВ первом случае будет выдано сообщение об ошибке, поскольку доступ к несуществующему свойству вернется
undefined
, и мы не сможем вызвать егоundefined
как функцию.Во втором случае будет сгенерирована ошибка, потому что мы снова не можем вызвать функцию как функцию.
Помните, что JavaScript - это язык со слабой типизацией. Мало или нет проверки типа происходит, если и пока это не должно. Код, который вы показали, работает в определенных случаях, потому что в этих случаях переданный объект имеет свойство с именем
toUpperCase
, то есть функция.Тот факт, что
obj
аргумент не гарантирует правильные типы свойств, вообще говоря, не беспокоит JavaScript. Он принимает отношение «жди и смотри» и не выдает ошибку, пока не возникнет реальная проблема во время выполнения.источник
Почти все в javascript может рассматриваться как объект. В вашем случае сам алфавит действует как строковый объект и
toUpperCase
может быть вызван как его метод. Квадратные скобки - это просто альтернативный способ доступа к свойствам объекта, и, посколькуtoUpperCase
это метод, следовательно, простой скобка()
необходима для['toUpperCase']
формирования['toUpperCase']()
.'a'['toUpperCase']()
эквивалентно'a'.toUpperCase()
источник
Здесь важно отметить, что, поскольку Javascript является динамическим языком, каждый объект, по сути, является просто прославленной хэш-картой ( с некоторыми исключениями ). И ко всему в объекте Javascript можно получить доступ двумя способами - обозначение скобки и обозначение точки.
Я быстро перейду к двум примечаниям, отвечающим на первую часть вашего вопроса, а затем я перейду ко второй части.
Обозначение в скобках
Этот режим больше похож на доступ к хеш-картам и массивам в других языках программирования. Вы можете получить доступ к любому компоненту (данным (включая другие объекты) или функции), используя этот синтаксис.
Это именно то, что вы делаете в своем примере. Вы имеете
'a'
, что является строкой (а не символьным литералом, как это было бы в языке, таком как C ++).Используя обозначение в скобках, вы получаете доступ к его
toUpperCase
методу. Но получить доступ к нему все еще недостаточно;alert
например, простой набор текста в Javascript не вызывает метод. Это просто простое утверждение. Для вызова функции необходимо добавить круглые скобки:alert()
показывает простое диалоговое окно, содержащееundefined
, так как не получило никаких параметров. Теперь мы можем использовать эти знания для расшифровки вашего кода, который становится:Что гораздо удобнее для чтения.
На самом деле, хороший способ понять это немного лучше - выполнить следующий Javascript:
Это вызывает
alert
, передавая ему функциональный объект, такжеalert
без выполнения второго предупреждения. Что показано (в Chrome 26, по крайней мере) следующее:Вызов:
показывает два последовательных окна сообщения, содержащие
undefined
. Это легко объяснить: внутреннийalert()
выполняется первым, показываетundefined
(потому что у него не было никаких параметров) и ничего не возвращает. Внешнее оповещение получает возвращаемое значение внутреннего оповещения, которое является ничем, и также отображаетсяundefined
в окне сообщения.Попробуйте все случаи на jsFiddle!
Точечная запись
Это более стандартный подход, который позволяет получить доступ к членам объекта с помощью
.
оператора dot ( ). Вот как ваш код будет выглядеть в точечной нотации:Гораздо более читабельно. Так, когда мы должны использовать точечную запись, и когда мы должны использовать скобочную запись?
сравнение
Основное различие между этими двумя методами семантическое. Есть и некоторые другие детали, но я вернусь к ним через секунду. Что наиболее важно, это то, что вы на самом деле хотите сделать - практическое правило заключается в том, что вы используете точечную нотацию для хорошо установленных полей и методов, которые есть у объекта, и скобочную нотацию, когда вы фактически используете свой объект в качестве хеш-карты ,
Отличный пример того, почему это правило так важно, может быть показан в вашем примере - поскольку код использует нотацию в скобках в месте, где точечная нотация была бы гораздо более разумной, это затрудняет чтение кода. И это плохо, потому что код читается намного чаще, чем пишется .
В некоторых случаях вы должны использовать скобочные обозначения, даже если использование точечных обозначений было более разумным:
если член объекта имеет имя, содержащее один или несколько пробелов или любые другие специальные символы, вы не можете использовать точечную запись:
foo.some method()
не работает, ноfoo["some method"]()
работает;если вам нужен динамический доступ к членам объекта, вы также застряли, используя скобки;
Пример:
Суть в том, что вы должны использовать скобочный синтаксис при использовании объекта в качестве хеш-карты (
foods["burger"].eat()
) и точечный синтаксис при работе с «фактическими» полями и методами (enemy.kill()
). Поскольку Javascript является динамическим языком, грань между «фактическими» полями и методами объекта и «другими» данными, хранящимися внутри, может быть довольно размытой. Но до тех пор, пока вы не перепутаете их, у вас все будет хорошо.Теперь перейдем к остальной части вашего вопроса (наконец-то !: P).
Ты не можешь Попытайся. Попробуйте позвонить
derp
по строке. Вы получите ошибку в строках:Да, в вашем случае так и должно быть. В противном случае вы получите ошибку, о которой я упоминал выше. Тем не менее, вам не нужно использовать
return obj[method]();
вcallMethod()
функции. Вы можете добавить свои собственные функции, которые затем используются функцией карты. Вот жестко закодированный метод, который превращает все буквы в заглавные:Код в учебнике, на который вы ссылаетесь, использует частичные функции . Они сами по себе хитрая концепция. Чтение большего количества об этом предмете должно помочь сделать вещи более ясными, чем я мог когда-либо сделать их.
Примечание: это код функции карты, используемый кодом в вопросе, источник здесь .
источник
Если вы спрашиваете, как это на самом деле работает, вот как я это читаю. Хорошо, это простая математическая функция. Чтобы понять это, нужно взглянуть на таблицу ascii. Который присваивает числовое значение каждой букве. Чтобы скрыть это, соревнование просто использует логическое выражение для преобразования, например If (ChcrValue> 80 && charValue <106) // Это набор строчных букв, тогда charValue = charValue - 38; // расстояние между нижним набором и верхним набором
это так просто, я на самом деле не удосужился найти правильные значения, однако это в основном переводит все строчные буквы в прописные.
источник
'a'['toUpperCase']()
работает. Но недоразумение понятно, если кто-то не прочитал вопрос.text-transform: uppercase
было добавлено ни одного стиля , я был в курсе того, как JS удалось изменить случай, очистить сомнение и узнать одну или две вещи. большое спасибо.