new操作符及原理
new
构造函数也是函数,唯一区别就是调用方式不同,任何函数只要使用new操作符调用就是构造函数,不适用new操作符调用的就是普通函数。
对象实例的创建过程:
- 在内存中创建一个新对象。
- 这个新对象内部的
[[Prototype]]
特性被赋值为构造函数的prototype
属性。 - 构造函数内部的
this
被赋值为这个新对象(即this
指向新对象)。 - 执行构造函数内部的代码(给新对象添加属性)。
- 如果构造函数返回对象,则返回该对象;否则,返回刚创建的新对象(空对象)。
第五步就已经说明了构造函数不同导致new
结果不同的原因
当代码 new Foo(…) 执行时,会发生以下事情:
一个继承自 Foo.prototype 的新对象被创建。
使用指定的参数调用构造函数 Foo,并将 this 绑定到新创建的对象。new Foo 等同于 new Foo(),也就是没有指定参数列表,Foo 不带任何参数调用的情况。
由构造函数返回的对象就是 new 表达式的结果。如果构造函数没有显式返回一个对象,则使用步骤1创建的对象。(一般情况下,构造函数不返回值,但是用户可以选择主动返回对象,来覆盖正常的对象创建步骤)
模拟:
function _new(constructor, ...args) { // 构造函数类型合法判断 if(typeof constructor !== 'function') { throw new Error('constructor must be a function'); } // 新建空对象实例 let obj = {}; // 将构造函数的原型绑定到新创的对象实例上 obj.__proto__ = Object.create(constructor.prototype); // 调用构造函数并判断返回值 let res = constructor.apply(obj, args); let isObject = typeof res === 'object' && res !== null; let isFunction = typeof res === 'function'; // 如果有返回值且返回值是对象类型,那么就将它作为返回值,否则就返回之前新建的对象 return isObject || isFunction ? res : obj; };
转载于:
https://juejin.cn/post/6994000994300330021