Js中的new原理及其实现

前几天遇到一个有趣的问题,代码如下:

function Person(){
  this.age = 0;
  setInterval(() => {
    this.age++;
  }, 1000);
}
var p = new Person();

运行起来会发现p值是一个动态改变的对象,那么它是怎么做到的呢?下面一起来看看:

// 直接运行Person方法并打印当前this对象
function Person(){
  this.age = 0;
  setInterval(() => {
    this.age++;
    console.log(this);
  }, 1000);
}
Person();
// 打印的结果是window对象

上面的代码我们直接运行了Person方法,发现此时打印的是window对象,原因是函数在调用的时候函数的this指向window,下面我们看一下通过new Person()运行的结果如何:

// 通过new Person()方式调用
function Person(){
  this.age = 0;
  // 这里不用箭头函数最后会指向window对象
  setInterval(() => {
    this.age++;
    console.log(this);
  }, 1000);
}
var p = new Person();
// 打印的结果是当前的p对象

运行上面的代码会发现打印了当前的p对象,不难看出,new语法改变了我们调用函数时候的this指向,并返回了执行后的this对象,那么它是怎么做到的呢?我们可以用一个简单的实现解释一下其原理:

function Person(age) {
  this.age = age;  
}
Person.prototype.sayAge = function () {
  console.log(this.age);
}
function createNew (target, ...argArr) {
  // 判断类型
  if (Object.prototype.toString.call(target).slice(8, -1) !== ‘Function‘) return;
  // 以构造器的prototype属性为原型,创建新对象;
  var source = Object.create(target.prototype);
  // 在source上执行target内容
  target.apply(source, argArr);
  // 返回执行后的source
  return source;  
}
var p = createNew(Person, 18);
console.log(p.age);
p.sayAge && p.sayAge();
// 打印结果为
// 18
// 18

另一种解释方式是:

var p = {};
p._ptoto_ = Person.prototype;
Person.apply(p, 18);

Over,自行理解吧~