Skip to content

判断 new 调用

javascript
function Foo() {
  // 判断自身是否被 new 关键字进行调用
}
Foo()
new Foo()

一、通过构造函数名称

javascript
function Foo() {
  const name = this.constructor.name
  if (name === 'Foo') {
    console.log('构造函数调用1');
  } else {
    console.log('普通函数调用1');
  }
}

二、通过元属性 new.target

javascript
function Foo() {
  const target = new.target
  if (target === undefined) {
    console.log('普通函数调用2');
  } else {
    console.log('构造函数调用2');
  }
}

三、通过构造函数对比

javascript
function Foo() {
  if (this.constructor === Foo) {
    console.log('构造函数调用3');
  } else {
    console.log('普通函数调用3');
  }
}

四、通过 [[prototype]] 属性

javascript
function Foo() {
  const p1 = Object.getPrototypeOf(this);
  const p2 = Foo.prototype;
  if (p1 === p2) {
    console.log('构造函数调用4');
  } else {
    console.log('普通函数调用4');
  }
}

Test Cases

javascript
describe('isNewCall', () => {
  let isNewCall;
  let Fn = () => {};
  function tester() {
    new Fn();
    expect(isNewCall).toBeTruthy();
    Fn();
    expect(isNewCall).toBeFalsy();
  }
  it('byConstructorName', () => {
    Fn = function () {
      const name = this.constructor.name;
      isNewCall = name === 'Fn';
    };
    tester();
  });
  it('byNewTarget', () => {
    Fn = function () {
      const target = new.target;
      isNewCall = target !== undefined;
    };
    tester();
  });
  it('byConstructorReference', () => {
    Fn = function () {
      isNewCall = this.constructor === Fn;
    };
    tester();
  });
  it('byPrototype', () => {
    Fn = function () {
      const p1 = Object.getPrototypeOf(this);
      const p2 = Fn.prototype;
      isNewCall = p1 === p2;
    };
    tester();
  });
});