前言
前段时间调试代码,查看对象的toString的返回数据,由于比较简单,直接在浏览器的控制台输出代码
{}.toString(); // Uncaught SyntaxError: Unexpected token .
“.”不是期待的表达式,{}在JS中不是一个再正常不过的对象么,于是试了一下其他对象类型数据。
[].toString(); // ""
function(){}.toString(); // Uncaught SyntaxError: Unexpected token (
/^\.$/.toString(); // "/^\.$/"
查资料看了一下,总的来说涉及到JS这门语言设计的几个概念:语句、函数声明、语句块等
语句
JS中,应用程序是由许多语法正确的语句组成的,语句的作用就是告诉浏览器应该怎样执行程序。语句之间使用“;”作为结尾,其中主要包括表达式语句、块语句、空语句和声明语句,这里不细讲。
注意上面一段话中的语法正确一词,在前言的demo代码中,数组和正则表达式可以正常调用的,但是对象和方法类型调用却是失败的,网上大部分答案回答都比较浅显:”JS中语句不能以function或者大括号作为开始,会报错“。对于这句话,只能说对错一半吧!
先来说一下为什么语句不能以”function“开始,这里涉及到函数声明的概念。
函数声明
函数声明:定义一个具有指定参数的函数,以function开头, 其中包括函数名,参数名,和函数语句块
举个栗子?:
function funcName(arg1, arg2) {
// 语句块
}
我们代码中调用toString方法”function(){}.toString“,是以”function“开头的, JS中会将以”function“ 开头的语句认定为函数声明语句,那么代码必须符合函数声明语句规范,很明显”function“后未包括函数名,这条函数声明语句明显不符合规范。
正确的做法:
// 以”(“开头的语句JS并不会将其视作函数声明
(function(){}).toString();
// 匿名函数
(function(){})()
// 匿名函数装B一点的写法
void function(){}()
非函数申明代码不可以“function”作为语句开头,那大括号又是怎么回事呢。
语句块
将零个或多个语句联合在一起,形成一条复合语句,用大括号将其包括
有的文档上叫“块语句”,也有人的文档上叫复合语句,举个栗子?,我们可以这样写代码:
{
console.info('输出一个语句');
console.info('不出错,是不是很神奇');
};
也就是说如果我们以大括号开头,浏览器会理解将其视作一个语句块,语句块中的代码和外面的代码并没有本质的区别,也是从上至下而执行。再看个栗子?:
{}; // undefined
{a: 'a'}; // 'a';
{a: 'a'}.a; // Uncaught SyntaxError: Unexpected token .
第一行很好理解,没有任何执行语句,当然输出undefined
第二行代码呢,输出“a”,这里不要被“:”给蒙蔽了,这里的的冒号是一个标识符,类似于C语言中的标记符,不同的是JS中通过“break”与“continue”跳转到标记符,二C语言中是通过“goto”,关于标记符
第三行代码等同于:“a: 'a'; .a;” 没有通过对象主体获取属性“a”,所以报错。
综上所述,“{}.toString();” 等同于: “; .toString();” 未通过对象主体调用“toString”方法,不符合JS中期待的表达式
说了这么多,用语句块有什么好处呢,我能想到的唯一好处只有“装B耍酷”...
总结在最后
JS语句为什么不能以“function”和大括号开头呢?
- 以function开头,但必须是一个函数声明语句
- 以大括号开头,但该大括号不再被当做一个对象处理,而是当做一个语句块处理
- 综上两条说明,JS语句可以以function,也可以以大括号作为开头,前提是必须符合JS中的语法规范
参考资料
MDN 语句
MDN 语句块
MDN 标记符
MDN Unexpected token
expressions-vs-statements
MDN Expressions_and_Operators
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。