脚本宝典收集整理的这篇文章主要介绍了深入聊一聊JS中new的原理与实现,脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。
new 运算符创建一个用户定义的对象类型的实例或具有构造函数的内置对象的实例。
使用new [constructor]的方式来创建一个对象实例,但构造函数的差异会导致创建的实例不同。
构造函数也是函数,其唯一的区别就是调用方式不同,任何函数只要使用 new 操作符调用就是构造函数,而不使用 new 操作符调用的函数就是普通函数。
因此构造函数也可以带有返回值,但是这会导致new的结果不同。
显然,打印的是{name:'Jalenl'}
function Person(age) { this.age = age; return { name: "Jalenl" }; } let obj = new Person(18); console.log(obj);
打印的是{name:'Jalenl'},也就是说return之前的定义都被覆盖了。这里return的是一个对象,那返回的是个基本类型呢?
function Person(age) { this.age = age; return 1; } let obj = new Person(18); console.log(obj);
返回{age:21},这么说return失效了,跟没有return一样的结果,那如果没有this绑定内部属性,再返回基本数据类型呢?
function Person(){ return 1 } new Person()
返回的是一个空对象{},意料之中。
综上,只有构造函数return返回的是一个对象类型时,才能改变初始结果。
ECMA-262 3rd. EdITion Specification中的说明了对象实例的创建过程:
13.2.2 [[Construct]]
When the [[Construct]] PRoperty for a Function object F is called, the following steps are taken:
- Create a new native ecmascript object.
- Set the [[Class]] property of Result(1) to "Object".
- Get the value of the prototype property of F.
- If Result(3) is an object, set the [[Prototype]] property of Result(1) to Result(3).
- If Result(3) is not an object, set the [[Prototype]] property of Result(1) to the original Object prototype object as described in 15.2.3.1.
- Invoke the [[Call]] property of F, providing Result(1) as the this value and providing the argument list passed into [[Construct]] as the argument values.
- If Type(Result(6)) is Object then return Result(6).
- Return Result(1).
总结下来就是:
第五步就已经说明了构造函数不同导致new结果不同的原因。
以下摘自MDN的解释:
当代码 new Foo(…) 执行时,会发生以下事情:
普通函数创建时,引擎会按照特定的规则为这个函数创建一个prototype属性(指向原型对象)。默认情况下,所有原型对象自动获得一个名为 constructor 的属性,指回与之关联的构造函数。
function Person(){ this.age = 18; } Person.prototype /** { constructor: ƒ Foo() __proto__: Object } **/
创建箭头函数时,引擎不会为其创建prototype属性,箭头函数没有constructor供new调用,因此使用new调用箭头函数会报错!
const Person = ()=>{} new Person()//TypeError: Foo is not a constructor
综上,熟悉了new的工作原理后,我们可以自己实现一个低配版的new,实现的关键是:
function _new(constructor, ...args) { // 构造函数类型合法判断 if(typeof constructor !== 'function') { throw new Error('constructor must be a function'); } // 新建空对象实例 let obj = new Object(); // 将构造函数的原型绑定到新创的对象实例上 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; };
这个低配版new实现可以用来创建自定义类的实例,但不支持内置对象,毕竟new属于操作符,底层实现更加复杂。
到此这篇关于JS中new的原理与实现的文章就介绍到这了,更多相关JS中new原理与实现内容请搜索脚本宝典以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本宝典!
以上是脚本宝典为你收集整理的深入聊一聊JS中new的原理与实现全部内容,希望文章能够帮你解决深入聊一聊JS中new的原理与实现所遇到的问题。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。