js变量后面加问号是什么_让人犯迷糊的变量声明!

3b960deb1c1ea2e6a65f428d07770a68.png

首先要明白一个机制:

先声明,后赋值!!!

var 

为什么会有这个机制?

这个要从内存角度去看:

变量是栈内存的 , 我们从栈内存,得到一块空间,我们把它的名字 命名为a (这就是 var a 做的事),无论这个空间里面放着什么,我们统统不要,把它换成 1 的二进制(a =1)

JS的弄巧成拙

以前程序员不懂内存,常常犯的问题就是: 用变量赋值之前却忘了声明

a = 1 
b = 2
console.log(a+b)

这很明显会报错的!

但是js为了讨好程序员,搞了一个语法糖 : 你忘记声明了,没关系,我来帮你声明!

这种情况下,上述的代码就可以正常运行了,你好我好大家好! ( ps:都可以想到一个大胖子手里端着咖啡,得意的笑*^_^* )

但是问题很快就接踵而至了!

js引擎执行过程:

  1. 检查语法错误
  2. 看到你变量没有声明,那就自动帮你声明
  3. 构建词法树,确定作用域
  4. 所有末定义直接赋值的变量自动声明为拥有全局作用域
  5. 运行代码,碰到函数嵌套,就利用callstack 来进行函数运行环境的切换

划重点了:所有末定义直接赋值的变量自动声明为拥有全局作用域!

那就造成了很多的问题:

  • 全局作用域的命名空间,受到了巨大的污染(可能变量重名,可能被人乱改)
  • 代码问题
var obj = {
sayHi:funciton(){
      a = 1
    console.log(a)
   }
}
var a = 3
function fn(){
    console.log(a)
}
obj.sayHi.call(obj)
fn.call()
------------------------------------------------------------------------------------
3 , 3

a=1 这里的a实际上是一个全局变量,被外面给修改成了3

在obj.sayHi()调用的哪一个瞬间,a已经改变了

那么如何解决这个问题呢

以前的程序员:

究竟是如何污染的呢?
function xx(){
   var a = 1
  console.log(a)
}
xx()
`再次分析这个代码:`
我们的本意,其实是想在 打印a,但是又不想把 a 暴露给全局, 因为可能有'重名',可能被人'乱改'!
所以,我们用函数作用域 , 也就是xx函数,包裹,这样有两个好处:
 1.我什么时候想用,就什么时候用
 2.a作为函数的属性,不会直接暴露给全局


`但是:`
 这个问题还是没有得到彻底解决------>因为我们还是在全局里面暴露了一个属性 ---> 函数xx!
     

`进一步:`
 如何解决函数暴露在全局的问题呢?
 
 '函数自调用!'
格式:
;(
 function (){
    逻辑; 
     
 }()
 )

我们写一个匿名函数,换句话说:'没有xx了'  自然也就不会暴露什么了
这个函数自己执行[后面跟了一个括号!]
最后在最外面套一层 (),解决语法报错问题!
最后加一个; 避免错误

这样太麻烦了,ES6就搞了一个let

let 的语法:
{
    let a = 1
}
定义了一个a ,这个a,只在 花括号里面起作用!
 
这样,就彻底解决了,变量暴露在全局的问题!!!

如何做js的面试题目?

  • 弄请js引擎的执行过程
  1. 画出词法树,注意末定义直接赋值的变量的变量提升
  2. 脑海中运行代码,根据不同的函数切换到不同的运行环境
  3. 搞清this是什么
  4. 搞清函数定义的时机和调用的时机

基本上所有的题目,都可以拿下了!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值