1. 程式人生 > >函式的引數作用域

函式的引數作用域

注意理解:

1、
var x = 1;

function f(x, y = x) {
  console.log(y);
  console.log(x);//undefined
}

f(2) // 2

2、
let x = 1;

function f(y = x) {
  let x = 2;
  console.log(y);
}

f() // 1

3、
function f(y = x) {
  let x = 2;
  console.log(y);
}

f() // ReferenceError: x is not defined

4、
var x = 1;

function foo(x = x) {
  // ...
}

foo() // ReferenceError: x is not defined

一旦設定了引數的預設值,函式進行宣告初始化時,引數會形成一個單獨的作用域,等到初始化完成,這個作用域就會消失,這種語法在不設定預設引數時是不會出現的。

所以:1、在x為新增預設值,y設定預設值為x,這時這個x在外部作用域已經定義,就會將這個值賦值給y,y=1.同理所以2中y=1。3中x在外部函式並沒有被定義,再賦值給y就會報錯。4中,引數的執行順序是從左到右的,所以這句話相當於:let x=x;因此會報錯。

再看一個更加複雜的例子:

var x = 1;
function foo(x, y = function() { x = 2; }) {
  var x = 3;
  y();
  console.log(x);
}

foo() // 3
x // 1

上面程式碼中,函式foo的引數形成一個單獨作用域。這個作用域裡面,首先聲明瞭變數x,然後聲明瞭變數yy的預設值是一個匿名函式。這個匿名函式內部的變數x,指向同一個作用域的第一個引數x。函式foo內部又聲明瞭一個內部變數x,該變數與第一個引數x由於不是同一個作用域,所以不是同一個變數,因此執行y後,內部變數x和外部全域性變數x的值都沒變。

變化其中的一小部分:

var x = 1;
function foo(x, y = function() { x = 2; }) {
  x = 3;
  y();
  console.log(x);
}

foo() // 2
x // 1

如果將var x = 3

var去除,函式foo的內部變數x就指向第一個引數x,與匿名函式內部的x是一致的,所以最後輸出的就是2,而外層的全域性變數x依然不受影響