makeCtor的源码:
function makeCtor () {
function constructor () {
return this.constructor.apply(this, arguments) || null;
}
return constructor;
}
这是一个闭包, 用途是在实例化class的时候执行Class的构造方法用的。
其实我现在也不是很明白它具体怎么用的,分析到它用的源码再详细写一下。不过我可以初步揣摩一下它的用法,先看一个简单的例子:
function A()
{
alert('a');
}
function B()
{
alert('b');
//this.constructor.apply(this,arguments); //<1>注释
}
var F = function(){};
F.prototype = A.prototype;
B.prototype = new F();
A.prototype.onlyId='only';
var b1 = new B();
console.log(b1.onlyId);//only
为什么是先写一个空函数F,然后再去F的原型对象指向A的原型对象,原因是这样的话可以不执行A的构造函数,也就是说此时这种方法是不会弹出alert(a)的,如何你直接将B的prototype指向new A(),那么会执行alert(a),此时也达到了继承的关系,打印b1的onlyId属性是‘only’,b1本身是没有onlyId属性的,它会去它的原型对象上找,这是js原型链关系。
如果此时把<1>注释放开的话,那么A的构造函数是会执行,也就是说会alert(a),原因是这句代码,this.constructor.apply(this,arguments);
apply的用法是fn.apply(this,arguments) 等于 this.fn(arguments),所以如果new B()的时候,this指向的是运行时上下文,也就是B,<1>处代码可以转换为 this.constructor(arguments),B会去原型对象上找constructor方法,也就是A(),会执行一遍A的构造函数。
-------------------------------------------
下面我们来讨论一下makeCtor在extjs里用法,纯粹是我揣摩,欢迎拍砖。
ExtJs4的makeCtor源码是这样的:
function makeCtor (className) {
function constructor () {
return this.constructor.apply(this, arguments) || null;
}
//<debug>
if (className) {
constructor.displayName = className;
}
//</debug>
return constructor;
}
后期把Base类的静态方法复制到类class上,class就是 class = makeCtor(类名字);
displayName = ‘类名字’,会将返回的constructor函数的名字改变,读者可以自己打印试试。
我理解返回的constructor并不是原型链上本来就有的constructor属性,只是一个构造函数,然后将构造函数的名字改成我们想要的类名,也就是返回的其实是一个普通的函数(这里是构造函数),然后将Base类的方法和属性复制到这个构造函数上,然后实例化这个函数,但是想不通为什么会返回
this.constructor.apply(this, arguments) || null;
new之后 在chrome调试下 会造成call 越界,堆栈溢出应该。想不通!!