JS简记-原型二
上一节我们以Object函数对象的prototype为例观察了一个对象的__proto__,这节我们再来看一下Function函数对象。
var f1 = new Function("name", "console.log(name);"); f1("zyong"); function f2(name){ console.log(name); } f2("zyong2");
我们可以看到两种方式声明的函数内容是一致的,且其都存在arguments(实参,函数运行前由引擎设置)、caller(调用者对象,函数运行前由引擎设置)、length(形参个数)、name(函数名?通过Object.getOwnPropertyDescriptor发现该属性不可写但可配置,所以将其改为可写后更新属性的值,属性值确实更新了,但最终呈现的函数名依旧是anonymous)等属性。
每一个函数对象都会存在prototype和__proto__属性,下面以f1为例来看:
prototype中有两个属性,constructor其实就是指向函数自身,__proto__则指向Object.prototype。
__proto__提供了许多我们常见的属性,比如bind、call、apply等函数。
_proto__中的get arguments/set arguments和get caller/set caller顾名思义是存取arguments和caller的,首先无法直接对两个属性进行设置(设置无效),然后通过Object.getOwnPropertyDescriptor观察到二者都是不可写且不可配置的,也就意味着无法手动使用Object.defineProperty通过修改value或setter更新二者的值,可以猜测,js试图防止人为的更新这两个属性,不但将“属性描述符”设置为不可写且不可配置,而且将setter方法设为空函数(函数内部无逻辑)。
1 function f(name){ 2 console.log(f.caller); 3 console.log(f.caller.a); 4 console.log(f.arguments); 5 } 6 (function f2(){ 7 f2.a = 1; 8 f("zyong"); 9 })();
控制台打印如下:
我们看到了f1函数对象的__proto__,那么可以肯定Function.prototype一定也是这个样子的,下面来可能Function的结构:
首先Function同样是一个函数,其同样拥有caller、arguments、length、name、prototype、__proto__属性,如期望的那样,prototype就是我们所预料的,而由于Function本身也是一个函数,所以其也需要call、apply、bind等属性,所以其__proto__如其他函数对象一样,也就是说Function的prototype和__proto__是一致的。