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
继承。
对此你有什么感觉呢,欢迎添加微信进行交流。