这里要注意的重要一点是,由于 Javascript 是一种动态语言,所以每个对象本质上只是一个美化的哈希映射(除了少数例外)。Javascript 对象中的所有内容都可以通过两种方式访问——括号表示法和点表示法。
我将快速回顾回答您问题第一部分的两个符号,然后我将进入第二部分。
括号符号
这种模式更类似于在其他编程语言中访问哈希图和数组。您可以使用此语法访问任何组件(数据(包括其他对象)或函数)。
这正是您在示例中所做的。你有'a'
,它是一个字符串(而不是字符文字,就像它在诸如 C++ 之类的语言中一样)。
使用括号表示法,您可以访问其toUpperCase
方法。但是访问它仍然不够;例如,在 Javascript 中简单地键入alert
不会调用该方法。这只是一个简单的陈述。为了调用该函数,您需要添加括号:alert()
显示一个包含 的简单对话框undefined
,因为它没有接收任何参数。我们现在可以使用这些知识来破译您的代码,它变成:
alert('a'.toUpperCase());
这更具可读性。
实际上,更好地理解这一点的一个好方法是执行以下 Javascript:
alert(alert)
这alert
通过将函数对象传递给它来调用,同样alert
,也不执行第二个警报。显示的内容(至少在 Chrome 26 中)如下:
function alert() { [native code] }
来电:
alert(alert())
显示两个连续的消息框,其中包含undefined
. 这很容易解释:内部alert()
首先执行,显示undefined
(因为它没有任何参数)并且什么都不返回。外部警报接收内部警报的返回值 - 什么都没有,并且还显示undefined
在消息框中。
尝试 jsFiddle 上的所有案例!
点符号
这是更标准的方法,它允许使用点 ( .
) 运算符访问对象的成员。这是您的代码在点表示法中的样子:
alert('a'.toUpperCase())
更具可读性。那么什么时候应该使用点符号,什么时候应该使用括号符号呢?
比较
这两种方法的主要区别在于语义。还有一些其他细节,但我会在稍后讨论。最重要的是您实际想要做的事情 - 经验法则是您使用点表示法表示对象具有的成熟字段和方法,而括号表示法表示您实际将对象用作哈希映射.
在您的示例中可以显示为什么此规则如此重要的一个很好的示例 - 因为代码在点表示法更明智的地方使用括号表示法,它使代码更难阅读。这是一件坏事,因为代码的读取次数比编写次数多得多。
在某些情况下,即使使用点表示法更明智,您也必须使用方括号表示法:
例子:
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)
您链接到的教程中的代码使用部分函数。它们本身就是一个棘手的概念。阅读更多关于该主题的内容应该有助于使事情变得比我所能做的更清楚。
注意:这是问题中代码使用的地图功能的代码,来源here。
function map(arr, iterator) {
var narr = [];
for (var i = 0; i < arr.length; i++) narr.push(iterator(arr[i], i));
return narr;
}