摘要:上面这段代码,在中的执行结果是什么呢大家思考分钟好,分钟已过,大家有结果了吗千万不要在浏览器的控制台中去写这段代码,虽然结果和你开始想的结果一样,但是,它是错误的。这是在控制台中执行的结果这是在中的执行结果可以看到两个结果是不一样的。
1. 引言
假设有这么一道题:
for (var i = 0; i < 10; i++) { console.log(i); for (var j = 0; j < 5; j++) { console.log(j); } } console.log("done");
我想要当 j = 2 的时候就退出所有的for语句,打印最后的 done ,你会怎么做?
可能有的同学会想到这样:
function foo () { for (var i = 0; i < 10; i++) { console.log(i); for (var j = 0; j < 5; j++) { console.log(j); if (j === 2) return; } } } foo(); console.log("done");
这样可以实现,但是又多写了一个函数,那么有没有别的办法呢?
再看一个例子,你也一定见到过这样的写法:
// 假设str是你通过ajax接收到的JSON串 var str = "{"name": "liu", "age": 20}"; var obj = eval("(" + str + ")"); console.log(obj);
那么,你有没有想过 eval 里面为什么要加上括号呢?如果不加又是什么情况?(提前剧透,不加括号这里会报错哦)。
接着往下看,当你读完这篇文章的时候,心中的疑惑会完全解开。
2. Label Statement学过C语言的同学知道,C的语法中有一个语句叫:goto,同时老师也多次强调不让我们使用goto语句,因为会大大影响程序的可读性和可维护性。
我们先来看一段C语言的goto代码:
void main(){ int a=2, b=3; if(a>b) { goto aa; } printf("hello"); aa: printf("s"); return 0; }
当 a < b 的时候,这里会打印字符串 "hello",然后结束。
当 a > b 的时候,由于goto语句的作用,就会跳过 print("hello"),直接跳到 aa 标签声明的代码块中,打印字符 "s",然后结束。
这就是goto语句的作用,通过标签声明一个代码块,然后在任何地方都可以执行 goto "labe" 来进行程序跳转。
显而易见,这样的写法,违背了程序顺序执行的原则,会跳来跳去,最后导致根本无法维护,所以,记住老师的话,不要使用 goto 语句。
那么,看完了C语言中的 goto 语句,和我们的 JavaScript 又有什么关系呢?
这就引出了今天的主题:Label Statement,它就是 JS 中的 goto 语句。
首先明确一个原则,在JavaScript中,语句优先。
也就是说,如果一段代码既能够以语句的方式解析,也能用语法的方式解析,在JS中,会优先按语句来解析。
{ a : 1 }
上面这段代码,在JS中的执行结果是什么呢?
大家思考2分钟....
好,2分钟已过,大家有结果了吗?
千万不要在浏览器的控制台中去写这段代码,虽然结果和你开始想的结果一样,
但是,它是错误的。
这是在console控制台中执行的结果:
这是在watch中的执行结果:
可以看到两个结果是不一样的。
console是经过处理的这里不能相信,watch是直接JS的运行环境执行后的结果,是正确的。
为什么 { a : 1 } 结果会是 1 呢?
我换一个写法:
{ a : 1 }
相信有的同学已经明白了,在JS中,{}既可以代表代码块,又可以作为Object的语法标志。
那么我们前面说过,JS是语句优先的,当一段代码既可以按照语句解析,又可以按照语法解析的时候,会优先按语句解析。
当把{}当做是代码块的时候,里面的 a : 1,是不是很像C语言goto语句的标签声明呢?
开头我们提出的第一个问题,如果用这种方式来解决,代码如下:
aa : { for (var i = 0; i < 10; i++) { console.log(i); for (var j = 0; j < 5; j++) { console.log(j); if (j === 2) break aa; } } } console.log("done");
aa是标签声明,包裹一个代码块,break 的作用是跳出当前的循环,本来是无法跳出外面那层for循环的,但是 break aa,这里跳出了整个代码块。
当然,这种写法是完全不提倡的,这里只是用来说明JS中的Label Statement这个特性,大家千万不要这样写代码。
再来看开头提出的第二个问题:
// 假设str是你通过ajax接收到的JSON串 var str = "{"name": "liu", "age": 20}"; var obj = eval("(" + str + ")"); console.log(obj);
我们知道,eval(str)会把接收到的字符串在当前上下文中执行,如果不加括号:
eval("{"name": "liu", "age": 20}}")
这里的执行语句就会变成:
{ "name" : "liu", "age" : 20 }
{}按照语句解析,执行里面的逗号表达式,我们知道逗号表达式要求每一项都必须是表达式,输出最后一项的结果,而这里不满足要求,所以会报错。
但是加上括号就变成了这样:
({ "name" : "liu", "age" : 20 })
小括号可以把里面的内容当做表达式来解析,那么里面的内容就是一个对象了。
这也是立即执行函数的原理:
(function () { console.log("IIFE"); })()
小括号把函数声明变成了函数表达式,后面再跟一个小括号表示调用。
4. 结束这里通过几个例子,引出了 JavaScript 的标签声明语句(Label Statement),从而解释了一些我们常用写法的原理。
以后万一有人问你为什么 eval() 解析JSON要加括号呢?
这回知道怎么说了吧。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/93897.html
摘要:表达式用来计算出一个值,语句用来执行以使某件事发生。其中,语句会立即退出循环,强制继续执行循环后面的语句。在执行语句之后,结果显示。语句语句的作用是指定函数调用后的返回值。语句语句的作用是把程序运行时产生的错误显式地抛出异常。 表达式在 JavaScript 中是短语,那么语句就是整句命令。表达式用来计算出一个值,语句用来执行以使某件事发生。从本质上看,语句定义了 JavaScript...
摘要:表达式语句把表达式当做语句的用法声明语句用来声明新变量或定义新函数控制结构改变语句的默认执行顺序条件语句循环语句跳转语句表达式语句赋值语句运算符函数调用等复合语句和空语句复合语句复合语句将多条语句联合在一起,当成一条单独的语句语句块的结尾不 表达式语句(expression statement):把表达式当做语句的用法; 声明语句(declaration statement):用来声...
摘要:系列文章核心概念本文浅尝最近因为工作上新产品的需要,让我有机会了解和尝试。这篇文章主要分享的是的核心概念,主要分为和四部分。再次强调,本文主要讲的是的核心概念,中所定义的类,都是设计类,并不是具体实现代码。 A query language created by Facebook for describing data requirements on complex applicati...
摘要:通过增加删除元素改变布局的。譬如和控制元素显示隐藏,或者改变元素行为的。譬如设计看过我之前介绍以手写依赖注入的朋友应该已经对行为驱动多少有些了解了。她有,并且包含了至少一个和一个标签。,将左边的事件传递给了右边的表达式通常就是事件处理函数。 前集回顾 在上一章里我们讲了如何为angular2搭建开发环境(还没搭起来的赶紧去看哦),并使之跑起来我们的第一个My First Angular...
摘要:前言基本上,我们每天都在和中的各种语句进行着沟通,那些我们经常见面的老朋友,或者是未曾见面的新朋友,它们共同维护着的流程,让我们的程序稳步运行。 前言 基本上,我们每天都在和 JavaScript 中的各种语句进行着 沟通 ,那些我们经常见面的 老朋友,或者是未曾见面的 新朋友 ,它们共同维护着 JavaScript 的流程,让我们的程序稳步运行。那么,你是否对它们足够了解呢 如果文章...
阅读 1120·2021-11-25 09:43
阅读 1569·2021-10-25 09:47
阅读 2464·2019-08-30 13:46
阅读 752·2019-08-29 13:45
阅读 1280·2019-08-26 13:29
阅读 2989·2019-08-23 15:30
阅读 1101·2019-08-23 14:17
阅读 1325·2019-08-23 13:43