new原理及模拟实现

简介new

new 运算符是建立一个用户定义的对象类型的实例或具备构造函数的内置对象的实例,其建立过程以下:javascript

  • 建立一个空的简单JavaScript对象(即{})
  • 连接该对象(即设置该对象的构造函数)到另外一个对象
  • 将第一步新建立的对象做为this的上下文
  • 若是该函数没有返回对象,则返回this

举个栗子:java

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

Person.prototype.sex = 'female';

Person.prototype.sayHello = function(){
    console.log('Hello!My name is ' + this.name);
}

var person = new Person('Youxuan','20');

console.log(person.name);   //Youxuan
console.log(person.habit);  //swim
console.log(person.sex);    //female
person.sayHello();  //Hello!My name is Youxuan

从上述内容中,能够看出实例访问到Person构造函数里的属性,
也能够访问到Person.prototype里的属性;
所以,咱们能够尝试模拟一下new的实现方法,先来回顾一下new是如何使用的数组

function Person(){
    ...
}
var person = new Person(...);
var person = newObject(...);

初步模拟

由于new的结果是一个对象,因此在实现new的过程当中,也要生成一个新的对象。咱们先将这个对象命名为obj,由于obj也具备Person构造函数的属性,全部要经过调用父类,继承父类实例的方式,来给obj添加新属性。微信

回顾上一篇文章,咱们讲解了原型和原型链,把obj的proto指向构造函数Person的原型对象prototype,此时便创建了obj对象的原型链:app

obj->Person.prototype->Object.prototype->null,实例以此关系来访问原型上的属性函数

function newObject(){
    var obj = new Object();
    Constructor = [].shift.call(arguments);
    obj.__proto__ = Constructor.prototype;
    Constructor.apply(obj,arguments);
    return obj;
}

在以上内容中,经过new Object()建立了一个对象obj。this

取出第一个参数,就是咱们要传入的构造函数。由于shift会修改原数组,因此arguments会被去除第一个参数。spa

将obj的原型指向构造函数,这样obj就能够访问到构造函数原型中的属性。prototype

利用apply,改变构造函数this指向到新建对象,这样obj就能访问到构造函数中的属性,而后返回obj。code

如今,咱们写一段代码来验证一下效果:

function Person(name,age){
    this.sex = 'female';
    this.age = age;
    return {
        name: name,
        habit: 'swim'
    }
}
var person = new Person('Youxuan','20');
console.log(person.name);   //Youxuan
console.log(person.habit);  //swim
console.log(person.sex);    //undefined
console.log(person.age);    //undefined

以上代码中,构造函数返回了一个对象,在实例person中只能访问返回的对象中的属性。

并且另需注意,这里返回的是一个对象,倘若须要返回一个基本类型的数据时该怎么办呢?

function Person(name,age){
    this.sex = 'female';
    this.age = age;
    return 'Beauty on my face'
}
var person = new Person('Youxuan','20');
console.log(person.name);       //undefined
console.log(person.habit);      //undefined
console.log(person.sex);        //female
console.log(person.age);        //20

这时结果跟上次彻底相反,尽管此次有返回值,可是至关于没有对返回值进行处理。

效果实现

因此仍需判断返回值是否是一个对象,若是是一个对象,就返回这个对象;若是不是一个对象,那就将它直接返回:

function newObject(){
    var obj = new Object();
    Constructor = [].shift.call(arguments);
    obj.__proto__ = Constructor.prototype;
    var demo = Constructor.apply(obj,arguments);
    return typeof demo === 'object' ? demo : obj;
}

至此就模拟实现了new操做符的效果,主要原理就是原型链apply继承。

对此你有什么感觉呢,欢迎添加微信进行交流。


图片描述

相关文章
相关标签/搜索