杂货小铺之作用域 🍟

2020-07-02  本文已影响0人  羊驼驼驼驼
js.jpeg

叮~,今天杂货小铺正式开业🎊,货架会不定期上新(好用的工具、日常小总结等等...)哦~

📌 敲好用的NRM源切换
Windows: npm install -g nrm
Mac: sudo npm install -g nrm 
  nrm ls (查看当前可用的源-带*的表示当前所用的源)
nrm.png
nrm test <源名称>(测试哪个源的速度比较快)
nrm.png
nrm use <源名称> (切换源)
nrm.png
nrm current (查看当前源)
nrm add <源名称> <源对应的地址> (定制源)
nrm del <源名称> (删除源 )
📌 唠唠作用域

常见的作用域主要分为:
🏖 全局作用域 => global/window
🏖 函数作用域 => function
🏖 块状作用域 => {}
🏖 动态作用域 => this

📖 变量在函数或代码块{}外定义,既为全局作用域。不过,在函数或代码块{}内定义的变量也是拥有全局作用域的(不推荐)。

 var a = 'hello'
 function foo() {
  // 函数内可调用a变量
  console.log(a)
 }
 // 在函数外定义的变量a拥有全局作用域,可以在任意地方被读取或修改
 // 如果变量在函数内没有声明(没有使用var关键字),该变量依然是全局变量
// 此处可调用a变量
console.log('函数外' + a)
function foo() {
  a = 'hello'
  // 此处可调用a变量
  console.log('函数内' + a)
}
// a当前在函数内,但是拥有全局作用域,将作为global/window的属性存在

🔎 \color{Orange}{Warning}:
在函数内部或代码块中没有定义的变量实际是作为global/window的属性存在,而不是全局变量。换句话说没有使用var定义的变量虽然拥有全局作用域,但是它是可以被delete的,而全局变量不可以。

📖 在函数内部定义的变量,就是局部作用域。对外是封闭的,从外层的作用域无法直接访问函数内部的作用域。

function foo() {
  var test = 'inner'
}
console.log(test) // 报错 ReferenceError: test is not defined

如果想要读取函数内的变量,必须借助return或者闭包

// return
function foo(val) {
  var test = 'inner'
  return test + val
}
console.log(foo('fun')) // innerfun

// 闭包
function foo(val) {
  var test = 'inner'
  var res = test + val
  function innser() {
    return res
  }
  return innser()
}
console.log(foo('fun')) // innerfun

// return 是函数对外交流的出口,而return可以返回的是函数
// 根据作用域的规则,函数内部的子函数可以获取函数作用域内的变量的

如果在函数innser再嵌套函数呢?这就会涉及到另一个概念:作用域链

scope.png

🔎 \color{Orange}{Warning}:
综合上图我们可以看到任何一个作用域链都是一个堆栈,首先先把全局作用域压入栈底,在按照函数的嵌套关系一次压入堆栈,在执行的时候按照这个作用域链寻找变量。

📖 在ES6之前没有自己的块状作用域的概念,在ES6中改变了这个现象,块状作用域得到普及。

if(true) {
  let a = 1;
  console.log(a)
}
// 在这个代码中,if后{}就是"块",这个里面的变量就存在于这个块级作用域
// 按照规则,{}之外是无法访问这个变量的

📖 this的指向

window.a = 3;
function test() {
  console.log(this.a)
}
test.bind({
  a: 5
})() // 5
test() // 3
// bind修改作用域的范围指向,而this指向的是当前的作用域对象

那现在来思考一个问题,作用域是在代码编写的时候决定的,还是在代码执行的时候才决定的?看一下🌰

var test = 'hello'
function foo() {
  // 函数内可调用test变量
  console.log(test)
}

🌻小葵花mama课堂开课啦🌻
在上述代码中test是全局作用域,函数内部用var定义的变量就是函数作用域,用专业术语来讲一哈就是:词法作用域。通俗的讲就是变量的作用域是在定义时决定而不是执行时决定,也就是说词法作用域取决于源码,通过静态分析就能确定,因此词法作用域也叫做静态作用域。相反,只能在执行阶段才能决定变量的作用域,就叫做动态作用域

function foo() {
  console.log(a) // 3
}
function bar() {
  var a = 3
  foo()
}
var a = 2
bar()

🎊 叮~
当foo()不能为a解析出一个变量引用时,它不会沿着嵌套的(语法)作用域链向上走一层,而是沿着调用栈向上走,以找到foo()是从何处被调用的。因为foo()是从bar()中调用的,它就会在bar()的作用域中检查变量。

上一篇 下一篇

猜你喜欢

热点阅读