How and why does 'a'['toUpperCase']() in JavaScript work?
javascript让我惊讶,这是另一个例子。我刚遇到一些我一开始不理解的代码。所以我调试了它并得出了这个结论:
1 | alert('a'['toUpperCase']()); //alerts 'A' |
现在,如果
不管怎样,
- 这是因为
toUpperCase 是"a"的成员吗?或者在幕后还有别的事情发生? 我正在阅读的代码具有以下功能:
1
2
3
4
5
6
7
8
9function 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函数的基本概念缺乏一些认真的理解。请帮助我理解这一点。
把它分解。
.toUpperCase() 是String.prototype 的一种方法。'a' 是一个原始值,但会转换为它的对象表示形式。- 我们有两个可能的符号来访问对象属性/方法,点和括号符号。
所以
1 | 'a'['toUpperCase']; |
是从
1 | 'a'['toUpperCase'](); |
1 | alert('a'.toUpperCase()) |
当使用
让我们来看看
首先,它返回一个以
在
您可以使用
1 2 3 4 5 6 | 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对象的"ToUpperCase"属性(在本例中是字符串类型)。
下面是我头顶上的一些代码:
1 2 3 4 5 6 7 8 9 10 11 | 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'](); |
当
请参见使用MDN中的对象。
In contexts where a method is to be invoked on a primitive string or a
property lookup occurs, JavaScript will automatically wrap the string
primitive and call the method or perform the property lookup.
您可以通过记录
所以在javascript中,
检索的工作原理是一样的。
因此,
但在我看来,编写map函数的更好方法是
touppercase是标准的javascript方法:https://developer.mozilla.org/en-us/docs/javascript/reference/global_objects/string/touppercase
它与
每个javascript对象都是一个哈希表,因此您可以通过指定一个键来访问其成员。例如,如果变量是字符串,那么它应该具有touppercase函数。所以,你可以通过
4所以,通过inline str,您可以在下面
1 | "a"["toUpperCase"]() |
几乎JavaScript中的所有内容都可以作为一个对象来处理。在您的示例中,字母表本身充当字符串对象,并且可以调用
1 2 | 'a'['toUpperCase']() // returns A 'a'.toUpperCase() // returns A |
But does that mean the specified method will already be an implicit member of the specified object?
不,有人可以通过一个物体
在第一种情况下,会引发一个错误,因为访问不存在的属性会返回
在第二种情况下,将引发一个错误,因为同样,我们不能将非函数作为函数调用。
记住,javascript是一种非常松散的类型语言。在必须进行类型检查之前,很少或没有进行类型检查。您显示的代码在某些情况下有效,因为在这些情况下,传递的对象有一个名为
可以说,
这里需要注意的重要一点是,由于JavaScript是一种动态语言,所以每个对象本质上都只是一个美化的哈希图(除了少数例外)。javascript对象中的所有内容都可以通过两种方式访问——括号表示法和点表示法。好的。
我会很快看一下回答你问题第一部分的两个符号,然后再看第二部分。好的。括号符号
此模式更类似于使用其他编程语言访问哈希图和数组。您可以使用此语法访问任何组件(数据(包括其他对象)或函数)。好的。
这正是您在示例中所做的。您有EDCOX1×0,它是一个字符串(而不是字符文字,就像它在一个语言中,比如C++)。好的。
使用括号表示法,可以访问它的
1 | alert('a'.toUpperCase()); |
可读性更高。好的。
实际上,更好地理解这一点的一个好方法是执行以下JavaScript:好的。
1 | alert(alert) |
它通过传递一个函数对象(也叫
1 | function alert() { [native code] } |
打电话:好的。
1 | alert(alert()) |
显示包含
在jsiddle上尝试所有案例!好的。点表示法
这是一种更标准的方法,它允许使用dot(
可读性更高。那么我们什么时候应该使用点符号,什么时候应该使用括号符号?好的。比较
这两种方法的主要区别在于语义。还有一些其他的细节,不过我马上就来。最重要的是你实际想要做的事情——经验法则是,你对一个对象拥有的已经建立好的字段和方法使用点表示法,当你实际使用你的对象作为散列图时使用括号表示法。好的。
这个规则为什么如此重要的一个很好的例子可以在您的示例中显示出来——因为代码在一个点表示法更明智的地方使用了括号表示法,这使得代码更难阅读。这是一件坏事,因为代码被读取的次数比被写入的次数要多。好的。
在某些情况下,即使使用点表示法更明智,也必须使用括号表示法:好的。
如果对象成员的名称包含一个或多个空格或任何其他特殊字符,则不能使用点表示法:
foo.some method() 不起作用,但foo["some method"]() 起作用;好的。如果需要动态访问对象的成员,还需要使用括号表示法;好的。
例子:好的。
1 2 3 | for(var i = 0; i < 10; ++i) { foo["method" + i](); } |
底线是,当使用对象作为散列映射(
现在,继续剩下的问题(最后!P)。好的。
how can I be sure method will always be a member of obj
Ok.
你不能。试试看。尝试在字符串上调用
1 | Uncaught TypeError: Object a has no method 'derp' |
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?Ok.
是的,在你的情况下,这是必须的。否则,你会得到我上面提到的错误。但是,在
1 2 3 4 5 6 7 8 9 | function makeCap() { return function(obj) { return obj.toUpperCase(); } } var caps2 = map(['a', 'b', 'c'], makeCap()); // ['A','B','C'] console.log(caps2) |
链接到的教程中的代码使用部分函数。它们本身就是一个棘手的概念。多读一些关于那个主题的书应该有助于使事情比我所能做的更清楚。好的。
注意:这是问题代码使用的map函数的代码,这里是源代码。好的。
1 2 3 4 5 | function map(arr, iterator) { var narr = []; for (var i = 0; i < arr.length; i++) narr.push(iterator(arr[i], i)); return narr; } |
好啊。
如果你问它实际上是如何工作的,那就是我如何阅读它。这是一个简单的数学函数。要理解它,您需要查看ASCII表。为每个字母指定一个数值。为了隐藏它,竞争只是使用一个逻辑语句来隐藏,例如if(chcrvalue>80&;charvalue<106)//这是一组小写字母那么charvalue=charvalue-38;//下集和上集之间的距离
这很简单,实际上我没有费心查找正确的值,但是这基本上是将所有小写字母都转换为大写值。