YGben

js变量


遇见 js ——解读 变量

历经7月加班的冲刷,来到了依旧热的八月。最近开始总结js基础点,年后几乎都在用js,所以完全是先实践后总结。

当我看到下面这段代码结果是 a=1, 一度懵逼,这是什么操作?

1
2
3
4
5
6
7
8
var a = 1;
function b() {
a = 10;
return;
function a() {}
}
b();
alert(a);

细细学习下才知涉及到两个关键点:

  1. var变量和函数声明提升
  2. js的变量是松散类型的
    翻译如下
1
2
3
4
5
6
7
var a=1;
function b(){
function a(){};
a=10;
return;
}
b();

解读: 函数变量声明提升所以 a()方法提升,此时a=10实则是给a函数方法赋值。js变量可以在修改变量值的同时修改值的类型。(ps 弱编程语言就是神奇,随便赋值,函数名居然可以用作变量名)。最后a就取值函数作用域外的值。即a=1

松散型

  • 变量可以保存任何类型的数据
1
2
3
4
5
6
7
8
var o = {
a:80,
b:function(){
return this.a
}
arr: ["1","2","3"]
}
console.info(o.b())

函数也可以,知道真相的我眼泪快要掉下来。

  • 可以在修改变量值的同时修改值的类型(不推荐)

块级作用域

  • 通过var关键字声明的变量作用域是函数作用域,没有块级作用域。
1
2
3
4
5
6
7
8
9
function func(){
if(!true){
var a=13;
}else{
console.log("----"+a);
}
}
func()
:----undefined

var 变量提升,作用域在函数func中,而不是if{}中。类似的for循环中i用var{}外还可以访问。

1
2
3
4
5
6
7
// var 变量提升至函数顶部
var a;
if(!true){
a=13;
}else{
console.log("----"+a);
}
  • ES6之前没有块级作用域,直到let const出现
1
2
3
4
5
6
7
8
9
function func(){
if(!true){
let a=13;
}else{
console.log("----"+a);
}
}
func();
:---ncaught ReferenceError: a is not defined

let为JS新增了块级作用域,不存在变量提升,不允许重复操作,只在块级中起作用。
let很方便的解决了没有块级作用域带来的不合理。

例如:想实现每隔10秒执行一次方法

1
2
3
4
5
6
for(var i=0;i<10;i++){
setTimeout(function(){
console.info("---"+i)
},10);
}
:---10(打印10次)

i 的作用域在for块级中,setTimeout延时function的执行,但是js代码不会同步等着执行,会继续执行直到i=10,最后一次执行10遍console.info(“—“+i)。

ES6以前可以这样解决:

1
2
3
4
5
6
7
for(var i=0;i<10;i++){
(function(m){
setTimeout(function(){
console.info("---"+m)
},10);
})(i)
}

i 传入 m,打印m,自然m只在外层function中起作用,m会保存每一个值,独立的。其实就是努力去创建一个独立的工作空间。可惜没有块级作用域这一说,所以才创建个函数作用域。

但是有了let 后,一切显得顺利成章。

1
2
3
4
5
for(let i=0;i<10;i++){
setTimeout((function(){
console.info("---"+i)
})(),10);
}

唯一的区别就是var改为let,便可实现效果。

以上只在考虑变量的因素,let和var及变量作用域。

想实现每隔10秒的执行一次的效果,还需要理解setTimeout,当执行最后一段代码时,会发现tong时间打印10条结果,并没有所谓的10秒一隔。

设定一个10ms 后执行的定时器并不代表这10ms后立即执行,只是表示10ms后被加入到队列中。加入队列中后并不代表立即执行,只能表示尽快执行。因为队列中并不只是你一个任务。

1
2
3
4
5
for(let i=0;i<10;i++){
setTimeout(function(){
console.info("---"+i)
},1000*i);
}

当然这样写准确地说也是大概时间。

总结:
var变量作用域在函数作用域,存在变量提升。let变量作用域在块级作用域,不会变量提升。