javascript new 操作符

275 阅读2分钟

在JavaScript中,函数是个很神奇的东西;

  1. 可以当做方法执行;
  2. 可以当做函数执行,返回值;
  3. 可以作为构造函数;

funcion Person(){ }

const p = new Person();

那么 new 函数到底做了什么?

此处要明白new是语言内操作符,它代表一系列动作,因此 new 时不仅仅是执行函数,还有更多的操作,执行函数仅仅是new操作符中的一个过程;

了解new的朋友都知道new的四部曲,我写了一个函数,来模拟new操作符的内部过程;

/**
 * 描述 创新对象工厂,类似new操作符的内部操作
 * @date 2021-06-23
 * @param {any} fn 构造函数
 * @param {any} ...args 待初始化的数据
 * @returns {any} 返回对象
 */
function objectFactory(fn, ...args) {
  // 1. 创建新建对象
  const obj = {};
  // 2. 新对象的 __proto__ 指向构造函数的 prototype 属性;
  obj.__proto__ = fn.prototype;
  // 3. 初始化属性,解决this绑定
  const result = fn.call(obj, ...args);
  // 4. 处理对象返回逻辑;
  // 返回新对象,如果存在 result,则返回result
  if (typeof result === 'object') {
    return result;
  }
  return obj;
}

/**
 * 描述 另一种实现
 * @date 2021-06-23
 * @returns {any}
 */
function objectNew() {
  // 构造函数
  const constructor = arguments[0];
  // 额外参数
  const args = Array.prototype.slice.call(arguments, 1);

  // 1. 创建新建对象
  let obj = {};
  // 2. 链接到原型
  obj = Object.create(constructor.prototype);
  // 3. 初始化属性,解决this绑定
  const result = constructor.apply(obj, args);
  // 4. 处理对象返回逻辑;
  // 返回新对象,如果存在 result,则返回result
  if (typeof result === 'object') {
    return result;
  }
  return obj;
}

/**
 * 描述 构造函数
 * @date 2021-06-23
 * @param {any} name
 * @param {any} address
 * @returns {any}
 */
function Person(name, address) {
  this.name = name;
  this.address = address;
  // 构造函数可以直接返回新对象,但不建议这么做,失去了构造函数本意;
  // return { a: name, b: address };
}

/**
 * 描述 给原型对象增加方法
 * @date 2021-06-23
 * @returns {any}
 */
Person.prototype.say = function () {
  console.log(`I am ${this.name} from ${this.address}`);
};

const p1 = objectFactory(Person, 'foo', 'hz');
const p2 = objectFactory(Person, 'bar', 'bj');

console.log(p1);
console.log(p2);
console.log(p1.__proto__ === p2.__proto__); // true
console.log(p1.__proto__ === Person.prototype); // true
console.log(p1.__proto__.__proto__ === Object.prototype); // true


const p3 = objectNew(Person, 'baz', 'nj');

console.log(p1.__proto__ === p3.__proto__); // true


函数 objectFactory 作用与 new 操作符内部过程是类似的,参数也是必要的,构造函数和其他属性值;

从原型结果 p1 查询原型链路, 与 new Person('foo','hz')效果等价;