JavaScript中定义函数,或者调用Function创建函数时,最终都会以类似这样的形式调用Function函
数:var newFun=Function(funArgs, funBody);
创建函数对象的主要步骤如下:
1. 创建一个build-in object对象fn
2. 将fn的内部[[Prototype]]设为Function.prototype
3. 设置内部的[[Call]]属性,它是内部实现的一个方法
4. 设置内部的[[Construct]]属性,它是内部实现的一个方法,
5. 设置fn.length为funArgs.length,如果函数没有参数,则将fn.length设置为0
6. 使用new Object()同样的逻辑创建一个Object对象fnProto
7. 将fnProto.constructor设为fn
8. 将fn.prototype设为fnProto
9. 返回fn
步骤1跟步骤6的区别为,步骤1只是创建内部用来实现Object对象的数据结构(build-in object
structure),并完成内部必要的初始化工作,但它的[[Prototype]]、[[Call]]、[[Construct]]等属性
应当为null或者内部初始化值,即我们可以理解为不指向任何对象(对[[Prototype]]这样的属性而
言),或者不包含任何处理(对[[Call]]、[[Construct]]这样的方法而言)。步骤6则将按照前面描述的
对象创建过程创建一个新的对象,它的[[Prototype]]等被设置了。
从上面的处理步骤可以了解,任何时候我们定义一个函数,它的prototype是一个Object实例,这样默
认情况下我们创建自定义函数的实例对象时,它们的Prototype链将指向Object.prototype。
chrome下例子:
function fn(args){return args;}
fn.__proto__ === Function.prototype //chrome下为:function Empty() {}
fn.prototype.constructor === fn
对象创建过程:
JS中只有函数对象具备类的概念,因此要创建一个对象,必须使用函数对象。函数对象内部有
[[Construct]]方法和[[Call]]方法,[[Construct]]用于构造对象,[[Call]]用于函数调用,只有使用
new操作符时才触发[[Construct]]逻辑。
var obj=new Object(); 是使用内置的Object这个函数对象创建实例化对象obj。var obj={};和var
obj=[];这种代码将由JS引擎触发Object和Array的构造过程。function fn(){}; var myObj=new fn();
是使用用户定义的类型创建实例化对象。
new Fn(args)的创建过程如下:
1. 创建一个build-in object对象obj并初始化
2. 如果Fn.prototype是Object类型,则将obj的内部[[Prototype]]设置为Fn.prototype,否则obj的
[[Prototype]]将为其初始化值(即Object.prototype)
3. 将obj作为this,使用args参数调用Fn的内部[[Call]]方法
3.1 内部[[Call]]方法创建当前执行上下文
3.2 调用F的函数体
3.3 销毁当前的执行上下文
3.4 返回F函数体的返回值,如果F的函数体没有返回值则返回undefined
4. 如果[[Call]]的返回值是Object类型,则返回这个值,否则返回obj
函数的prototype被赋给派生对象隐式[[Prototype]]属性,这样根据Prototype规则,派生对象和函数
的prototype对象之间才存在属性、方法的继承/共享关系。