应无所住,而生其心
排名
1
文章
860
粉丝
112
评论
163
net core webapi post传递参数
庸人 : 确实坑哈,我也是下班好了好几次,发现后台传递对象是可以的,但...
百度编辑器自定义模板
庸人 : 我建议换个编辑器,因为现在百度富文本已经停止维护了,用tinymec...
ICP备案 :渝ICP备18016597号-1
网站信息:2018-2025TNBLOG.NET
技术交流:群号656732739
联系我们:contact@tnblog.net
公网安备:50010702506256
欢迎加群交流技术

旧时的 "var"

4711人阅读 2019/3/19 10:27 总访问:5193927 评论:2 收藏:0 手机
分类: Js相关


在第一章关于变量那部分,我们提到了变量声明的三种方式:

let

const

var


let 和 const 在词法环境中的行为完全一样。

但是 var 却是一头源自旧时代的怪兽。在现代脚本中一般不再使用,但它仍存在于陈旧的脚本里。

如果你不打算见识这样的脚本,你可以跳过或推迟阅读这一章,但是你有可能会踩到它的坑。


乍看之下,var 和 let 的行为相似,即声明变量:

  1. function sayHi({
  2.   var phrase = "Hello"// 局部变量,使用 "var",而不是 "let"
  3.   alert(phrase); // Hello
  4. }
  5. sayHi();
  6. alert(phrase); // 报错:phrase is not defined

…但两者存在区别。



“var” 没有块级作用域

用 var 声明的变量,不是函数范围就是全局的,它们在块内是可见的。

举个例子:

  1. if (true) {
  2.   var test = true// 用 "var" 而不是 "let"
  3. }
  4. alert(test); // true,变量在 if 结束后仍存在


如果我们在第二行使用 let test,那么 alert 就无法访问到它。因为 var 忽略块级代码,所以我们得到了一个全局的 test。

循环也是这样,var 无法成为块级或循环的局部变量:


  1. for (var i = 0; i < 10; i++) {
  2.   // ...
  3. }
  4. alert(i); // 10, "i" 在循环结束后仍然可见,它会成为一个全局变量


如果一段代码块位于函数内部,那么 var 会成为一个函数级的变量:

  1. function sayHi({
  2.   if (true) {
  3.     var phrase = "Hello";
  4.   }
  5.   alert(phrase); // works
  6. }
  7. sayHi();
  8. alert(phrase); // 报错:phrase is not defined

可以看到,var 穿透了 if、for 或其它块级代码。这是因为在早期的 JavaScript 里,块没有词法环境。而 var 就是对它的一个回忆。


“var” 在函数开头被处理

var 声明在函数开始时处理(或者全局声明之于脚本开始)。

换言之,var 变量会在函数开头被定义,与它在代码里定义的位置无关(这里不考虑定义在嵌套函数里的场景)。

如下代码:


  1. function sayHi({
  2.   phrase = "Hello";
  3.   alert(phrase);
  4.   var phrase;
  5. }


…它完全等同于这个(var phrase 被上提到函数开头):

  1. function sayHi({
  2.   var phrase;
  3.   phrase = "Hello";
  4.   alert(phrase);
  5. }

…甚至是这种的(记住,代码块是会被忽略的):

  1. function sayHi({
  2.   phrase = "Hello"// (*)
  3.   if (false) {
  4.     var phrase;
  5.   }
  6.   alert(phrase);
  7. }

这种行为一般称为「提升」,因为所有的 var 都会被「提升」到函数的顶部。

所以在上面的例子中,if (false) 分支永远都不会执行,但没关系,它里面的 var 会在函数开始时被处理,所以在执行 (*)那行代码时,变量是存在的。

声明会被提升,但是赋值不会。

我们最好用例子来说明:

  1. function sayHi({
  2.   alert(phrase);
  3.   var phrase = "Hello";
  4. }
  5. sayHi();


var phrase = "Hello" 这行包含两个步骤:

使用 var 声明变量;

使用 = 给变量赋值。

声明在函数执行的开始进行(「提升」),但是赋值是在它出现的地方,所以代码实际上是这样工作的:

  1. function sayHi({
  2.   var phrase; // 声明在开头工作……
  3.   alert(phrase); // undefined
  4.   phrase = "Hello"// ...赋值 — 当执行到这里时。
  5. }
  6. sayHi()


因为所有的 var 声明都是在函数开头处理的,我们可以在任何地方引用它们,但是在它们被赋值之前都是 undefined。

上面两个例子中 alert 运行不会报错,因为变量 phrase 是存在的,但是它还没有被赋值,所以它表现为 undefiend。

总结

总结

var 声明变量有两点主要区别:

  1. 变量没有块作用域,它们在最小函数级可见;

  2. 变量声明在函数开头处理。

涉及全局对象时,还有一个小的区别,我们会在下一章讲解。

这些区别实际上很多时候都不是好事。首先,我们无法创建块级局部变量。而且变量提升会造成更多的错误。所以,在新近的脚本里,

  1. var
 就很少见了。


转自:https://zh.javascript.info/var



欢迎加群讨论技术,1群:677373950(满了,可以加,但通过不了),2群:656732739。有需要软件开发,或者学习软件技术的朋友可以和我联系~(Q:815170684)

评价