前几天遇到一个有趣的问题,代码如下:
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,自行理解吧~