TypeScript基础入门 - 变量声明(一)
转载地址
TypeScript基础入门 - 变量声明(一)
项目实践仓库
https://github.com/durban89/typescript_demo.git tag: 1.0.3
为了保证后面的学习演示需要安装下ts-node,这样后面的每个操作都能直接运行看到输出的结果。
npm install -D ts-node
后面自己在练习的时候可以这样使用
npx ts-node src/learn_basic_types.ts
npx ts-node 脚本路径
变量声明
let和const是JavaScript里相对较新的变量声明方式。 像我们之前提到过的, let在很多方面与var是相似的,但是可以帮助大家避免在JavaScript里常见一些问题。 const是对let的一个增强,它能阻止对一个变量再次赋值。
因为TypeScript是JavaScript的超集,所以它本身就支持let和const。 下面我们会详细说明这些新的声明方式以及为什么推荐使用它们来代替 var。
如果你之前使用JavaScript时没有特别在意,那么这节内容会唤起你的回忆。 如果你已经对 var声明的怪异之处了如指掌,那么可以了解加深下记忆。
var 声明
一直以来我们都是通过var关键字定义JavaScript变量。
var a = 10;
大家都能理解,这里定义了一个名为a值为10的变量。我们也可以在函数内部定义变量:
function f() { var message = "Hello, world!"; return message; }
并且我们也可以在其它函数内部访问相同的变量。
function f() { var a = 10; return function g() { var b = a + 1; return b; } } var g = f(); console.log(g());
运行后得到的结果如下
11
上面的例子里,g可以获取到f函数里定义的a变量。 每当 g被调用时,它都可以访问到f里的a变量。 即使当 g在f已经执行完后才被调用,它仍然可以访问及修改a。
function f() { var a = 1; a = 2; var b = g(); a = 3; return b; function g() { return a; } } console.log(f());
运行后得到的结果如下
2
作用域规则
对于熟悉其它语言的人来说,var声明有些奇怪的作用域规则。 看下面的例子:
function f(shouldInitialize: boolean) { if (shouldInitialize) { var x = 10; } return x; } console.log(f(true)); console.log(f(false));
运行后得到的结果如下
10 undefined
有些读者可能要多看几遍这个例子。 变量 x是定义在*if语句里面*,但是我们却可以在语句的外面访问它。 这是因为 var声明可以在包含它的函数,模块,命名空间或全局作用域内部任何位置被访问,包含它的代码块对此没有什么影响。 有些人称此为 *var作用域或函数作用域*。 函数参数也使用函数作用域。这些作用域规则可能会引发一些错误。 其中之一就是,多次声明同一个变量并不会报错:
function sumMatrix(matrix: number[][]) { var sum = 0; for (var i = 0; i < matrix.length; i++) { var currentRow = matrix[i]; for (var i = 0; i < currentRow.length; i++) { sum += currentRow[i]; } } return sum; }
这里很容易看出一些问题,里层的for循环会覆盖变量i,因为所有i都引用相同的函数作用域内的变量。 有经验的开发者们很清楚,这些问题可能在代码审查时漏掉,引发无穷的麻烦。
捕获变量怪异之处
下面的代码会返回什么:
for (var i = 0; i < 10; i++) { setTimeout(function() { console.log(i); }, 100 * i); }
介绍一下,setTimeout会在若干毫秒的延时后执行一个函数(等待其它代码执行完毕)。
好吧,看一下结果:
10 10 10 10 10 10 10 10 10 10
很多JavaScript程序员对这种行为已经很熟悉了。 大多数人期望输出结果是这样:
0 1 2 3 4 5 6 7 8 9
还记得我们上面提到的捕获变量吗?
我们传给setTimeout的每一个函数表达式实际上都引用了相同作用域里的同一个i。
让我们花点时间思考一下这是为什么。 setTimeout在若干毫秒后执行一个函数,并且是在for循环结束后。 for循环结束后,i的值为10。 所以当函数被调用的时候,它会打印出 10!
一个通常的解决方法是使用立即执行的函数表达式(IIFE)来捕获每次迭代时i的值:
for (var i = 0; i < 10; i++) { (function (i) { setTimeout(function () { console.log(i); }, 100 * i); })(i); }
运行后的结果如下
0 1 2 3 4 5 6 7 8 9
这种奇怪的形式我们已经司空见惯了。 参数 i会覆盖for循环里的i,但是因为我们起了同样的名字,所以我们不用怎么改for循环体里的代码。
本实例结束实践项目地址
https://github.com/durban89/typescript_demo.git tag: 1.0.4
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
编程从业五年的十四条经验你掌握了吗?
排列不分先后: 1. 当性能遇到问题时,如果能在应用层进行计算和处理,那就把它从数据库层拿出来。排序和分组就是典型的例子。在应用层做性能提升总是要比在数据库层容易的多。就像对于MySQL,SQLite更容易掌控。 2. 关于并行计算,如果能避免就尽量避免。如果无法避免,记住:能力越大,责任越大。如果有可能,尽量避免直接对线程操作。尽可能在更高的抽象层上操作。例如,在iOS中,GCD,分发和队列操作是你的好朋友。人类的大脑没有被设计成用来分析那些无穷临时状态——这是我的惨痛教训所得。 3. 尽可能简化状态,尽可能局部本地化。适用至上。 4. 短小可组合的方法是你的好朋友。 5. 代码注释是危险的,因为它们很容易更新不及时或给人误导,但这不能成为不写注释的理由。不要注释鸡毛蒜皮的事情,但如果需要,在某些特殊地方,战略性的长篇注释是需要的。你的记忆会背叛你,也许会在明天早上,也许会在一杯咖啡后。 6. 如果你认为一个用例场景也许“不会有问题吧”,它也许就是一个月后让你在发布的产品中遭受惨痛失败的地方。做一个怀疑主义者,测试,验证。 7. 有疑问时,和团队中所有相关人交流。 8. 做正确的事情...
- 下一篇
Laravel - Artisan
0. 查看已有命令 php artisan list 1. 一般命令 命令 作用 参数 clear-compiled 清除已编译好的类文件 - down 使该项目进入 “维护模式” --message[=MESSAGE] 关于 “维护模式” 的信息--retry[=RETRY] 设置重新执行命令的时间(秒) env 查看项目所处环境(server) - help 输出某个命令的帮助信息 --format=FORMAT 以一定格式存储帮助信息(txt, xml, json, or md) [默认: "txt"]--raw 输出命令原生帮助信息 inspire 随机输出一条鼓励语句 - list 查看现有所有命令 同 help make (类别名) migrate 运行数据库迁移 --database[=DATABASE] 设置使用的数据库--force 在生产环境中强制运行命令--path[=PATH] 数据迁移文件执行路径--pretend 不执行 SQL 查询--seed 同时执行数据填充--step 强制执行迁移,可单独回滚 optimize 优化框架 --force 强制编译类文...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- Docker安装Oracle12C,快速搭建Oracle学习环境
- CentOS6,CentOS7官方镜像安装Oracle11G
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- CentOS关闭SELinux安全模块
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16
- Hadoop3单机部署,实现最简伪集群
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果