基础——重中之重之JS的变量的声明
基础——重中之重之js的变量的声明
在现在这个浮躁的前端圈,人们盲目学着所谓火热的框架,都多多少少疏忽了基础,但任其框架万变,都万变不离其宗——js尔。
本系列课程着重讲解js中基础,一些容易忽略的知识。
js的变量声明
说起变量声明大家都是十分熟悉的,在js声明一个新变量可以用var,const或者let, 他们属于js里面的操作符,接下来我们来依次聊一下他们
0.无操作符的情况
在js里面也是支持直接把变量直接赋值不需要声明的,如:
a = 1; console.log(a); // 1 console.log(window.a) // 1
这种情况,会创建一个全局变量, 在严格模式(严格模式是es5出的, ie10之前不支持)下会报错,项目中极其不推荐这样做,很容易导致变量覆盖引发不可预知的bug,
目前前端的ide多数会自动检测(如webstorm),给予一个弱警告,推荐配置eslint
1.var
js是弱类型语言,var声明的变量无需指定类型, 也可以只声明不赋值,如果只声明会保存一个特殊的值——undefined,如下:
var a; console.log(a === undefined); // true
提升
var声明变量会导致提升情况, 如下面的代码
console.log(a === undefined); // true var a; console.log(b === undefined); //uncaught referenceerror: b is not defined
变量提升是js引擎解释执行代码前所做的工作,或者说js编译时,顺便提一下,在《你不知道的javascript上卷》1.1节中,作者有提到js是编译语言,并给出了解释,
尽管我们把js归为“动态”和“解释执行”的语言,有兴趣的可以去看一下。下面再给出两个例子
//eg.1 a = 1; var a; console.log(a); // 1;
如果从直觉上看,认为js执行时是由上而下一行一行执行力的, 我们会认为结果是undefined,再看一个例子
//eg.2 console.log(a); var a = 1;
你猜结果如何? referenceerror或者是1? 结果其实undefined。
当你看到var a = 1可能认为这是一个声明, 对于js而言, 其实是两个步骤, 声明var a和赋值a = 1,但第一步在编译阶段进行的。
所以上面两个例子的处理流程为
var a; a = 1; console.log(a);
var a; console.log(a); a = 1;
全局作用域下声明变量会绑定在全局对象上(window)
未测试node.js
var a = 1; console.log(window.a); // 1;
顺便提一下, 带有id的dom元素为将其绑定在window上,key为id,如
<script > console.log(window.testid === document.getelementbyid('testid')); // true </script>
2.let
let是var的兄弟,在es6中引入的新关键字,把变量隐式地劫持在了其作用域(通常是{...}中),如:
if (true) { let a = 1; } console.log(a); // referenceerror
let循环
for循环是let发挥优势的典型例子, 这里相对于var减少了副作用,如:
for (var i = 0; i < 10; i++) { } console.log(i); // 10 for (let j = 0; j < 10; j++) { } console.log(j); // referenceerror
let不存在var一样的变量提升
这个特性是需要稍微注意的
console.log(a); //referenceerror let a = 1;
typeof 不再是绝对安全的操作
以前我们判断一个变量存不存在会用到 typeof, 因为即使变量不存在也不会报错, 但如果用了let就不一样了, 如:
console.log(typeof a); // undefined console.log(typeof b); //uncaught referenceerror: b is not defined let b;
这个属于暂时性死区(tdz), 即只要进入当前块级作用域,所使用的变量已经存在了,但在声明之前都属于死区,不可进行操作。
全局作用域下声明变量不会绑定在全局对象上(window)
let a = 1; console.log(window.a); // undefined;
3.const
const也是es6引入的新关键词, 它除了拥有let上面介绍的特性外,还有两条特性:
1.const声明的变量是不可修改的。
2.const声明的变量必须是其作用域内未定义过的
const a = 1; a = 2; //uncaught typeerror: assignment to constant variable.
var a = 1; const a = 2; //uncaught syntaxerror: identifier 'a' has already been declared
关于项目中使用
目前国内的占比还是不能肆意妄为的使用es6的特性的, 不过有类似babel之类的转换器,可以让我们写代码时可以用es6的一些新特性,兼容问题交给转换器来做。
不过我们要明白一点,转换器不是真正意义上的做到完美,他能做得是一些语法糖的兼容,js引擎的跨度不是全都能由代码补丁解决的,举个例子,es5新增对象属性劫持
是没办法在ie8以下实现的,(ps:司徒正美用ie独自支持的vbscript在avalon.js中实现了, vbscript不算js)。
如果项目中配了babel,只是让我们的代码更规范,减少错误,我们代码中的用到的let,const在babel中都会变成var, 类似这样的语法糖兼容起来要么是无法做到的,
要么兼容起来需要极大量代码的,最后折中处理了。
这里说一个在不支持let的环境里模拟其作用域特性的代码
// 模拟 let a = 1; try { throw 1; } catch (a) { console.log(a); // 1 } console.log(a); // uncaught referenceerror: a is not defined
代价就是这么大, ┑( ̄д  ̄)┍
上一篇: 这应该就是所谓的猫科男票吧!
下一篇: vscode中使用git