使用函数调用作为默认参数 javascript

Using a function call as default parameter javascript

帮助我理解为什么我不能执行以下操作:

function rgb(r = 0, g = 0, b = 0) {
  this.r = r % 255
  this.g = g % 255
  this.b = b % 255,
    this.str = function() {
      return `rgb(${this.r}, ${this.g}, ${this.b})`
    }
}

function rect(w, h, x, y, rgb = new rgb()) {
  this.dim = {
    w: w,
    h: h
  }
  this.pos = {
    x: x,
    y: y
  }
  this.rgb = rgb
}

我收到以下错误(调用 rect() 时):

ReferenceError: can't access lexical declaration `rgb' before initialization

function rgb(r = 0, g = 0, b = 0) {
  this.r = r % 255
  this.g = g % 255
  this.b = b % 255,
    this.str = function() {
      return `rgb(${this.r}, ${this.g}, ${this.b})`
    }
}

function rect(w, h, x, y, rgb = new rgb()) {
  this.dim = {
    w: w,
    h: h
  }
  this.pos = {
    x: x,
    y: y
  }
  this.rgb = rgb
}

const r = new rect(1, 2, 3, 4);

rgbrect定义在同一个文件中,rgb定义在rect之前。

您的变量名有冲突。您在顶层有一个 rgb 函数,但在 rect 的参数列表中也有一个 rgb 参数。在参数列表中,当引用变量名时,解释器将尝试查找变量名绑定到什么——如果参数列表已经有该变量名,它将引用该绑定。所以 new rgb() 正在引用尚未初始化的参数 rgb

这不是确切地正在发生的事情,但参数列表的范围看起来 就像声明参数名称一样用let,然后赋值,例如

的作用域
const fn = (a, b, c = 'bar') => {
  console.log('fn invoked');
};

类似于:

const fn = (argA, argB, argC) => {
  let a;
  let b;
  let c;
  a = argA;
  b = argB;
  c = argC === undefined ? 'bar' : argC;
  fnBody(a, b, c);
};
const fnBody = (a, b, c) => {
  console.log('fn invoked');
}

这样做rgb = new rgb()就像

let rgb;
rgb = argRGB === undefined ? new rgb() : argRGB
//                               ^^^ reference to un-initialized variable

出于类似的原因,您可以这样做:

const fn = (a, b = a) => {
  console.log(a, b);
};

fn('foo');

同样,在声明变量时,在变量完成初始化之前,您不能引用正在声明的变量的名称:

const foo = null || foo;

准确的函数名称也有助于防止错误。考虑更改为:

function makeColors(r = 0, g = 0, b = 0) {
  this.r = r % 255;
  this.g = g % 255;
  this.b = b % 255;
  this.str = function() {
    return `rgb(${this.r}, ${this.g}, ${this.b})`
  };
}

function rect(w, h, x, y, colors = new makeColors()) {
  this.dim = {
    w: w,
    h: h
  }
  this.pos = {
    x: x,
    y: y
  }
  this.colors = colors
}

const r = new rect(3, 4, 5, 6);
console.log(r);