Здесь важно отметить, что, поскольку Javascript является динамическим языком, каждый объект, по сути, является просто прославленной хэш-картой ( с некоторыми исключениями ). И ко всему в объекте Javascript можно получить доступ двумя способами - обозначение скобки и обозначение точки.
Я быстро перейду к двум примечаниям, отвечающим на первую часть вашего вопроса, а затем я перейду ко второй части.
Обозначение в скобках
Этот режим больше похож на доступ к хеш-картам и массивам в других языках программирования. Вы можете получить доступ к любому компоненту (данным (включая другие объекты) или функции), используя этот синтаксис.
Это именно то, что вы делаете в своем примере. Вы имеете 'a'
, что является строкой (а не символьным литералом, как это было бы в языке, таком как C ++).
Используя обозначение в скобках, вы получаете доступ к его toUpperCase
методу. Но получить доступ к нему все еще недостаточно; alert
например, простой набор текста в Javascript не вызывает метод. Это просто простое утверждение. Для вызова функции необходимо добавить круглые скобки: alert()
показывает простое диалоговое окно, содержащее undefined
, так как не получило никаких параметров. Теперь мы можем использовать эти знания для расшифровки вашего кода, который становится:
alert('a'.toUpperCase());
Что гораздо удобнее для чтения.
На самом деле, хороший способ понять это немного лучше - выполнить следующий Javascript:
alert(alert)
Это вызывает alert
, передавая ему функциональный объект, также alert
без выполнения второго предупреждения. Что показано (в Chrome 26, по крайней мере) следующее:
function alert() { [native code] }
Вызов:
alert(alert())
показывает два последовательных окна сообщения, содержащие undefined
. Это легко объяснить: внутренний alert()
выполняется первым, показывает undefined
(потому что у него не было никаких параметров) и ничего не возвращает. Внешнее оповещение получает возвращаемое значение внутреннего оповещения, которое является ничем, и также отображается undefined
в окне сообщения.
Попробуйте все случаи на jsFiddle!
Точечная запись
Это более стандартный подход, который позволяет получить доступ к членам объекта с помощью .
оператора dot ( ). Вот как ваш код будет выглядеть в точечной нотации:
alert('a'.toUpperCase())
Гораздо более читабельно. Так, когда мы должны использовать точечную запись, и когда мы должны использовать скобочную запись?
сравнение
Основное различие между этими двумя методами семантическое. Есть и некоторые другие детали, но я вернусь к ним через секунду. Что наиболее важно, это то, что вы на самом деле хотите сделать - практическое правило заключается в том, что вы используете точечную нотацию для хорошо установленных полей и методов, которые есть у объекта, и скобочную нотацию, когда вы фактически используете свой объект в качестве хеш-карты ,
Отличный пример того, почему это правило так важно, может быть показан в вашем примере - поскольку код использует нотацию в скобках в месте, где точечная нотация была бы гораздо более разумной, это затрудняет чтение кода. И это плохо, потому что код читается намного чаще, чем пишется .
В некоторых случаях вы должны использовать скобочные обозначения, даже если использование точечных обозначений было более разумным:
если член объекта имеет имя, содержащее один или несколько пробелов или любые другие специальные символы, вы не можете использовать точечную запись: foo.some method()
не работает, но foo["some method"]()
работает;
если вам нужен динамический доступ к членам объекта, вы также застряли, используя скобки;
Пример:
for(var i = 0; i < 10; ++i) {
foo["method" + i]();
}
Суть в том, что вы должны использовать скобочный синтаксис при использовании объекта в качестве хеш-карты ( foods["burger"].eat()
) и точечный синтаксис при работе с «фактическими» полями и методами ( enemy.kill()
). Поскольку Javascript является динамическим языком, грань между «фактическими» полями и методами объекта и «другими» данными, хранящимися внутри, может быть довольно размытой. Но до тех пор, пока вы не перепутаете их, у вас все будет хорошо.
Теперь перейдем к остальной части вашего вопроса (наконец-то !: P).
как я могу быть уверен, что метод всегда будет членом obj
Ты не можешь Попытайся. Попробуйте позвонить derp
по строке. Вы получите ошибку в строках:
Uncaught TypeError: Object a has no method 'derp'
Это своего рода общая функция для вызова ЛЮБЫХ методов для ЛЮБОГО объекта. Но значит ли это, что указанный метод уже будет неявным членом указанного объекта?
Да, в вашем случае так и должно быть. В противном случае вы получите ошибку, о которой я упоминал выше. Тем не менее, вам не нужно использовать return obj[method]();
в callMethod()
функции. Вы можете добавить свои собственные функции, которые затем используются функцией карты. Вот жестко закодированный метод, который превращает все буквы в заглавные:
function makeCap()
{
return function(obj) {
return obj.toUpperCase();
}
}
var caps2 = map(['a', 'b', 'c'], makeCap()); // ['A','B','C']
console.log(caps2)
Код в учебнике, на который вы ссылаетесь, использует частичные функции . Они сами по себе хитрая концепция. Чтение большего количества об этом предмете должно помочь сделать вещи более ясными, чем я мог когда-либо сделать их.
Примечание: это код функции карты, используемый кодом в вопросе, источник здесь .
function map(arr, iterator) {
var narr = [];
for (var i = 0; i < arr.length; i++) narr.push(iterator(arr[i], i));
return narr;
}
arr[5]
. Если числа , где действительные имена идентификаторов можно использовать точечную нотацию:arr.5
.