参数也有作用域?来看看这道题你真的懂了吗

前言

函数传参时,参数也具有作用域,你遇到过吗?当我听到的时候也觉得不可思议,因为在日常开发中基本不会遇到类似的代码,只有可能在一些面试题可能会遇到,考察的是对函数总体的了解程度吧。今天让我们来详细聊聊函数中的参数作用域。

image.png

例题

看下面代码,思考它的输出

var x = 0
var k = 99
function bar(s = () => { console.log(this); }) {
  var j = 'zj'
  function foo(x,
    y = function () { x = 3; k = 100; j = 'yy'; console.log(x); },
    a = () => { console.log(this); }
  ) {
    console.log(x)
    var x = 2
    var k = 88
    console.log(j);
    y()
    a()
    console.log(x)
    console.log(k)
  }

  foo.call({ name: 'ving' }, 1)
  console.log(j);
  s()
}
bar.call({ name: 'king' })
console.log(x)
console.log(k)

复制代码

看完了,你的答案是什么?

// 1
// zj
// 3
// {name:ving}
// 2
// 88
// yy 
// {name:king}
// 0
// 100
复制代码

答对的帅哥可以把嚣张打在评论上

image.png

反正我看完是这样的

image.png

解析

首先让我们来了解了解什么是参数作用域?
参数作用域是怎么形成的,每一个函数都有参数作用域吗?
不,只有当函数的参数有默认值时, 函数会形成一个新的作用域, 这个作用域用于保存参数的值。即现在函数有两个作用域了,一个参数作用域一个函数体作用域。
那么这两个作用域有啥关系呢?
没有关系,开玩笑。准确来说还是有一点关系的。这两个作用域是相互独立的(没有包含关系!!!),它们之间的联系只能通过参数来进行交流。也就是说当参数作用域改变了参数的值就会影响到函数体作用域中的该值的变化。这样说有点抽象,等会通过代码来分析就明白了。 另外需要注意的是:参数作用域的上层作用域和函数体作用域的上层作用域是相同的。

var x = 0
var k = 99
function bar(s = () => { console.log(this); // 八 }) {
  var j = 'zj'
  function foo(x,
    y = function () { x = 3; k = 100; j = 'yy'; console.log(x); // 三 },
    a = () => { console.log(this);// 四 }
  ) {
    console.log(x) // 一
    var x = 2
    var k = 88
    console.log(j); // 二
    y()
    a()
    console.log(x) // 五
    console.log(k) // 六
  }

  foo.call({ name: 'ving' }, 1)
  console.log(j); // 七
  s()
}
bar.call({ name: 'king' })
console.log(x) // 九
console.log(k) // 十

复制代码

如上,我标明了代码执行顺序,我们来一步一步解析。
一:函数预解析变量提升后foo传值1改变 x = 1
二:参数作用域与函数体作用域独立,所以访问的是上层作用域bar中的j = 'zj'
三: 参数作用域有x若没有则会找bar--> window 不会去foo函数体作用域找!所以 x = 3
四:a为箭头函数,箭头函数指向上层作用域。(参数作用域的上层作用域和函数体作用域的上层作用域是相同的)所以this = {name:ving} 看下面代码和图解析

function bar(s = () => {  console.log(this); // { name: 'king' } }) {
  const jj = () => {
    console.log(this); // { name: 'king' }
  }
  jj()
  s()
}
bar.call({ name: 'king' })
复制代码

画图

image.png

五:函数体作用域有值 x = 2
六: 同上 k = 88
七:函数体作用域有值 但是执行过程三时,j被重新赋值 所以 j = 'yy'
八:同四例题 即 this = {name:king}
九: x = 0 过程三执行时改变的是第一个参数x不是全局x所以全局没变化
十: k = 100 过程三执行时改变的是全局的k 因为参数作用域没有k且上层作用域也没有,只能找到顶层window中的k

end

看完了,懂了!

image.png

简单总价下这类题目的重点:
1.参数作用域和函数体作用域相互独立但是它们的上层作用域是相同的。
2.this指向:参数作用域中的箭头函数里的this指向的是其上一作用域,是其本身的this

记住这两点,以后类似题目都是换汤不换药了。
点个赞吧!彦祖

image.png

猜你喜欢

转载自juejin.im/post/7079266572115640357
今日推荐