JavaScript一直让我惊讶,这是另一个例子。我只是遇到了一些代码,一开始我不理解。所以我对它进行了调试,得到了这样的发现:

alert('a'['toUpperCase']());  //alerts 'A'

现在,如果toUpperCase()被定义为string类型的成员,这肯定是显而易见的,但最初对我来说没有意义。

不管怎么说,

does this work because toUpperCase is a member of 'a'? Or there is something else going on behind the scenes? the code I was reading has a function as follows: 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 It is kinda generic function to call ANY methods on ANY object. But does that mean the specified method will already be an implicit member of the specified object?

我确信我对JavaScript函数的基本概念缺少一些认真的理解。请帮助我理解这一点。


当前回答

您可以使用.propertyName表示法或["propertyName"]表示法访问任何对象的成员。这就是JavaScript语言的特点。为了确保该成员在对象中,只需检查它是否被定义:

function callMethod(method) {
    return function (obj) {
        if (typeof(obj[method]) == 'function') //in that case, check if it is a function
           return obj[method](); //and then invoke it
    }
}

其他回答

在Javascript中,对象就是对象。这就是它们的性质{}。对象属性可以使用以下任意一种来设置:a.greeting = 'hello';或者a['greeting'] = 'hello';。两种方法都有效。

检索的工作原理相同。a.greeting(不带引号)是'hello', a['greeting']是'hello'。例外:如果属性是一个数字,则只有括号方法有效。点方法没有。

a是一个带有toUpperCase属性的对象它实际上是一个函数。您可以检索该函数并随后以'a'.toUpperCase()或'a'['toUpperCase']()两种方式调用它。

但在我看来,更好的方法来写地图函数将是 Var caps = ['a','b','c']。map(函数(char){返回char. touppercase ();}) 那么谁需要callMethod函数呢?

基本上javascript把所有东西都当作一个对象,或者说每个对象都可以被看作一个字典/关联数组。函数/方法的定义方式与对象完全相同——作为这个关联数组中的一个条目。

本质上,你是在引用/调用(注意'()')' a'对象的'toUpperCase'属性(在这里是字符串类型)。

以下是我脑海中的一些代码:

function myObject(){
    this.msg = "hey there! ;-)";
    this.woop = function(){
        alert(this.msg); //do whatever with member data
    }
}

var obj = new myObject();
alert( obj.msg );
alert( obj['msg'] );
obj['woop']();

这里需要注意的重要一点是,由于Javascript是一种动态语言,因此每个对象本质上都只是一个美化过的哈希映射(有少数例外)。Javascript对象中的所有内容都可以通过两种方式访问——括号表示法和点表示法。

我会快速地过一遍这两个符号来回答你问题的第一部分,然后我会讲第二部分。

括号

这种模式更类似于访问其他编程语言中的hashmap和数组。您可以使用此语法访问任何组件(数据(包括其他对象)或函数)。

这正是您在示例中所做的。你有一个'a',它是一个字符串(而不是字符字面量,就像在c++等语言中那样)。

使用括号符号,您可以访问它的toUpperCase方法。但仅仅获取信息还不够;例如,简单地在Javascript中输入alert,并不会调用该方法。这只是一个简单的陈述。为了调用函数,您需要添加圆括号:alert()显示了一个包含undefined的简单对话框,因为它没有接收到参数。我们现在可以利用这些知识来破译你的代码,它变成:

alert('a'.toUpperCase());

这样可读性更强。

实际上,更好地理解这一点的一个好方法是执行以下Javascript:

alert(alert)

它通过传递一个函数对象来调用alert,同样是alert,而不执行第二个alert。所显示的内容(至少在Chrome 26中)如下:

function alert() { [native code] } 

调用:

alert(alert())

显示包含undefined的两个连续消息框。这很容易解释:内部alert()首先被执行,显示为undefined(因为它没有任何参数)并且没有返回任何东西。外部警报接收内部警报的返回值-这是空的,并且在消息框中显示为undefined。

在jsFiddle上尝试所有的案例!

点符号

这是一种更标准的方法,允许使用点(.)操作符访问对象的成员。这是你的代码在点表示法下的样子:

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;
}

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'表示您正在引用'a'字符串对象的'toUpperCase'属性,然后调用它()。

每个JavaScript对象都是一个哈希表,因此你可以通过指定一个键来访问它的成员。例如,如果一个变量是一个字符串,那么它应该有toUpperCase函数。你可以通过

var str = "a"
str['toUpperCase'](). // you get the method by its name as a key and invoke it.

通过inline str,你可以有下面

"a"["toUpperCase"]()