Skip to content
本页目录

new 关键字

实现步骤

实现 new 之前,我们需要理解 new 实例化构造函数时做了哪些事情(以下是 JS 高级程序设计中的说法):

  1. 创建一个新对象;
  2. 将构造函数的作用域赋给新对象(因此 this 就指向了这个新对象);
  3. 执行构造函数中的代码(为这个新对象添加属性);
  4. 返回新对象

实现代码

使用示例

我们先看如何使用这个将被实现的 _new 方法:

JS
// Person 构造函数
function Person(name, age) {
  this.name = name;
  this.age = age;
}

// 第一个参数是构造函数,后面是参数列表
// 所以 _new 函数需要取出 arguments 第一个参数,它就是构造函数
let person = _new(Person, 'zhang', 18);
// Person 构造函数
function Person(name, age) {
  this.name = name;
  this.age = age;
}

// 第一个参数是构造函数,后面是参数列表
// 所以 _new 函数需要取出 arguments 第一个参数,它就是构造函数
let person = _new(Person, 'zhang', 18);

ES5 实现

JS
// ES5 写法,因为不知道参数有多少个,所以只能通过内部的 arguments 参数类数组进行获取
function _new() {
    // 1 创建一个新对象
    var obj = new Object();

    // 2. 将构造函数的作用域赋给新对象
    // 2.1 我们需要先获取到构造函数
    var Fn = [].shift.call(arguments);
    // 2.2 将构造函数的作用域赋给新对象
    obj.__ptoto__ = Fn.prototype;

    // 3. 执行构造函数中的代码 注意:此时arguments已经在上一步中被转为数组,且去掉了第一个参数
    var result = Fn.apply(obj, arguments);

    // 4. 返回新对象 注意:需要判断返回 null 与 function 情况
    return result instanceof Object ? result : obj;
}
// ES5 写法,因为不知道参数有多少个,所以只能通过内部的 arguments 参数类数组进行获取
function _new() {
    // 1 创建一个新对象
    var obj = new Object();

    // 2. 将构造函数的作用域赋给新对象
    // 2.1 我们需要先获取到构造函数
    var Fn = [].shift.call(arguments);
    // 2.2 将构造函数的作用域赋给新对象
    obj.__ptoto__ = Fn.prototype;

    // 3. 执行构造函数中的代码 注意:此时arguments已经在上一步中被转为数组,且去掉了第一个参数
    var result = Fn.apply(obj, arguments);

    // 4. 返回新对象 注意:需要判断返回 null 与 function 情况
    return result instanceof Object ? result : obj;
}

ES6 实现

JS
// ES6 写法,因为 ES6 增加了 rest 参数,这样可以很方便的接受其它参数
function _new(fn, ...args) {
    // 整合了1、2步
    const obj = Object.create(fn.prototype);

    const result = fn.apply(obj, args);

    // 如果函数返回 非空并是对象 返回 value 否则 返回 obj
    return result instanceof Object ? result : obj;
}
// ES6 写法,因为 ES6 增加了 rest 参数,这样可以很方便的接受其它参数
function _new(fn, ...args) {
    // 整合了1、2步
    const obj = Object.create(fn.prototype);

    const result = fn.apply(obj, args);

    // 如果函数返回 非空并是对象 返回 value 否则 返回 obj
    return result instanceof Object ? result : obj;
}