实现new方法(附加instanceof)

488 阅读2分钟

在这里简单介绍一下new方法,以及手动实现一个new方法。

new的作用

常言道,没有对象怎么办? new一个!

new主要是用来构造对象的,下面来一个例子:

function Person(name, age) {
  this.name = name;
  this.age = age;
}

let p = new Person('yan', 18);

上面的例子中,我们可以使用new运算符作用于一个函数上,构造出一个对象。

new出来对象的__proto__属性

在控制台打印下上面例子中的p,可以看到,对象的__proto__指向了其构造函数的prototype属性

p.__proto__ === Person.prototype    //true

上面的代码也可以验证这个理论

构造函数的return

下面来几个例子

//0. 构造函数没有用return直接返回
function Person(name, age) {
  this.name = name;
  this.age = age;
}
let p = new Person('yan', 18);
console.log(p);    //Person {name: "yan", age: 18}

//1. return基本类型
function Person(name, age) {
  this.name = name;
  this.age = age;
  return 1;
}
let p = new Person('yan', 18);
console.log(p);    //Person {name: "yan", age: 18}

//2.return 对象
function Person(name, age) {
  this.name = name;
  this.age = age;
  return {};
}
let p = new Person('yan', 18);
console.log(p.name);    //undefined

从上面的例子中,可以看出: 如果该函数没有返回对象,则返回this

实现new

mdn new

更多new方法的详细介绍,可以参考mdn上的文档,其中文档上说new 关键字会进行如下的操作:

  • 创建一个空的简单JavaScript对象(即{};
  • 链接该对象(设置该对象的constructor)到另一个对象,即 protp === fn.prototype;
  • 绑定this;
  • 返回值的确定

以上几点我们也得到了证实,下面根据上面几点,我们来实现一个new方法:

function myNew() {
   // 拿到要作用的构造函数和参数
   let [constructor, ...args] = [... arguments];
   // 简单处理下箭头函数不可以作为构造函数
   if(constructor.toString().includes('=>')) {
      throw '箭头函数不能作为构造函数';
   }
   //0. 创建一个空对象
   let obj = {};
   //1. 将对象的原型指向构造函数中的prototype属性
   obj.__proto__ = constructor.prototype;
   //2. 绑定this指向
   let res = constructor.apply(obj, args);
   //3. 返回值问题,如果该函数没有返回对象,则返回this
   return res instanceof Object ? res : obj;
}


//简单验证下
function Person(name, age) {
  this.name = name;
  this.age = age;
  return 1;
}
let p = myNew(Person,'yan', 18);  //Person {name: "yan", age: 18}

这样,就简单实现了一个new方法。

instanceof

上面我们手写new方法的时候,用到了一个方法instanceof,这里对其做个简单介绍:

作用

instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。要记住,是原型链上!

function Preson(){} 
function User(){} 
var p = new Preson();
p instanceof Preson; // true,因为 Object.getPrototypeOf(p) === C.prototype
p instanceof User; // false

p instanceof Object; // true,因为 Object.prototype.isPrototypeOf(p) 返回 true
Preson.prototype instanceof Object // true,同上

语法

object instanceof constructor

  • object 某个实例对象
  • constructor 某个构造函数

手动实现

/**
* 如果对象和构造函数的原型链顶端一致,则返回true,否则返回false
*/
function myInstanceOf(object, constructor) {
   //构造函数的protype
   const baseProto = constructor.prototype;
   //原型链顶端
   const topProto = Object.__proto__;
    while(topProto !== null){
        if(topProto === baseProto){
            return true
        }else {
            topProto = topProto.__proto__
        }
    }
    return false
}