面试中遇到关于JavaScript中new关键字背后的实现原理,了解大概的原理,但是表达出来不是很清楚,表示掌握得不够完全,这里查了一些资料,做一下整理。
原理
例如我们做了new的调用操作,
1 | new ConstructorFunction(arg1, arg2); |
new操作
背后实际上发生了这些步骤:
- 创建一个新的空对象,对象类型为简单的object
- 设置这个空对象的实例原型(内部的、不可访问的[[prototype]]属性,部分浏览器可通过
__proto__
进行访问,ES5开始可通过Object.getPrototypeOf(obj)
取得)为构造函数的prototype
属性(每个函数对象都拥有一个prototype
属性) - 让
this
变量指向这个新创建的对象 - 以这个新创建的对象为上下文执行构造函数
- 如果构造函数有返回非空的对象,则返回该对象,否则返回第一步中创建的对象。
原型的几个概念
这里涉及到几个概念:
- 构造函数,配合使用new关键字的函数可称为构造函数
- 实例原型对象,在Ecma标准中,通过
[[prototype]]
表示,在部分浏览器中使用__proto__
(非标准的,不建议使用)来表示,ES5开始可使用Object.getPrototypeOf()
读取,ES6开始可使用Object.setPrototypeOf()
方法进行设置(仅支持完全替换对象或者设为null) - 原型对象,构造函数的
prototype
属性
比较难理解的是[[prototype]]
这个属性,每个对象都拥有一个内部的[[prototype]]
属性。这个对象是创建对象的时候设置的,创建包括new
、通过Object.create()
或者用文本字面量,并且只能通过Object.getPrototypeOf()
和Object.setPrototypeOf()
方法进行操作。
原型链和继承
说明
一旦通过new操作实例化一个对象后,如果这个实例上查找某个属性并不存在,脚本会通过[[prototype]]
对象向上一级继续查找,也就是通过原型链的方式进行往上查找。这种方式和在传统的类继承方式是类似的,在JavaScript中通过原型链的形式来继承父类的属性和方法。
函数中,除了拥有隐藏的[[prototype]]
属性,还有一个prototype
属性,这个属性可以访问、修改和添加希望给实例继承的属性和方法。
原型链实例
1 | ObjMaker = function() { this.a = 'first'; } |
继承实例
1 | SubObjMaker = function() {}; |
实现
1 | function newOperator(ConStr, args) { |
欢迎访问我的博客 https://blog.bookcell.org