new运算符

js中增加了new能够依据构造函数新建一个对象

  function Person () {    this.name = 'mike';    this.age = 24;  }

js中任何函数都能够视为构造函数,只须要在调用函数的时候增加一个new运算符:

  • 上述函数如果间接调用Person(),将间接执行,将name与age绑定在global对象上,而在浏览器环境,global个别即window,故执行后能够失去
window.name === 'mike'; // truewindow.age === 24; // true
  • 若增加new运算符,即new Person(),运行后果将返回一个对象,对象上绑定了name和age
const person = new Person();person.name === 'mike'; // trueperson.age === 24; // trueconsole.log(window.name, window.age); // undefined, undefined

new的实现

new运算符理论进行了三步操作

  • 新建一个对象
  • 在新建对象上新建__proto__属性,并指向构造函数的原型
  • 以新建对象作为上下文上运行构造函数
function new() {    // 新建对象    const obj = {};    // 拆散出第一个参数,即传入的构造函数    const constructor = [].shift.call(arguments);    // 新建__proto__属性    obj.__proto__ = constructor.prototype;    // shift曾经将构造函数拆散进来了,这里的arguments只剩下构造函数入参    // 以obj作为上下文运行构造函数    constructor.apply(obj, arguments);    return obj;}const person = new(Person);person instanceOf Person; // true

用new运算符和执行new()的成果等同。

  • 另外须要留神一下,每创立一个函数对象,零碎都会给他增加一个prototype属性,指向他的原型对象,而这个原型对象上会默认失去一个constructor属性,指向他的构造函数,即指向该函数对象自身,从而实现原型链
  • 又因为函数自身也是一个对象,它相当于继承自Function对象,即function Person()等价于Person = new Function(),所以函数自身也有原型链
  • 而原型也是一个对象,继承自Object对象,也有原型链
  • 最初,Object原型对象就是最原始的对象,他的__proto__属性为null,联合上述例子
const person = new Person();// person和Person不间接产生分割,通过原型对象产生分割person.__proto__ === Person.prototype; // truePerson.prototype.constructor === Person; // truePerson.prototype.__proto__ === Object.prototype; // trueObject.prototype.constructor === Object; // trueObject.prototype.__proto__ === null; // true// Function.prototype上有各种办法通用的办法,如apply以及callPerson.__proto__ === Function.prototype; // trueFunction.prototype.constructor === Function; // trueFunction.prototype.__proto__ === Object.prototype; // trueObject.prototype.constructor === Object; // trueObject.prototype.__proto__ === null; // true