var __extends = function (e, t) {
function r() {
this.constructor = e
}
for (var n in t)
if (t.hasOwnProperty(n))
e[n] = t[n];
r.prototype = t.prototype;
e.prototype = new r
};
我理解的是把t中的属性都拷贝到e当中,不知道是否有误?
为什么要声明一个r并且把他的构造函数指向e?
在实际业务中能起到什么作用?
我的理解:
如果只是把t中的属性都拷贝到e当中,那么三行代码就搞定了:
for (var n in t)
if (t.hasOwnProperty(n))
e[n] = t[n];
那段代码的原意应该是除了复制属性以外,还要建立e和t之间的继承关系,让e看起来是继承了t的属性,所以把t的prototype赋值给了e。
这一段代码的目的是继承。for
那一句实现的作用却是是 t 中的属性拷贝到 e 中,但是我觉得不太好。我喜欢的方式是这一句改成e._SUPER_=t.prototype
。这样 e 依旧可以通过e._SUPER_.construtor
访问 t 中的属性。毕竟拷贝的话还涉及深拷贝和浅拷贝,e改变t中某些属性是对象的代码上也比较明显。这个比较简单。
e.prototype = new r
,这一句是为了实现原型链的继承。这一句之后就导致(实现这个只能通过new
)e.prototype.[[prototype]] = t.prototype
就是说一个内部属性e.prototype.[[prototype]]
指向了t
的原型。当我们创建一个新的对象obj = new e
的时候,就是obj.[[prototype]]
指向了e.prototype
。
当我们读取一个对象的属性,obj.propertyname
其实是相当于执行下面的递归函数。
read(obj,propertyname)
{
if(obj[propertyname]) return obj[propername];
// if(!obj.[[prototype]]) return undefined; //先忽略这句吧
return read(obj.[[prototype]],propertyname);
}
就是说读的时候会递归的查找obj.[[prototype]]
中有没有这个属性,这个递归的终点就是 Object.prototype
,所有的obj.[[prototype]].[[prototype]]。。。
最终的结果都是指向Object.protoype
(Object.prototype没有[[prototype]]),所以加在Object.prototype
中的属性,所有对象都能访问。这样obj = new e
就可以访问e.prototype
中的属性了(如果obj没有重载的话)。e.prototype=new r
的作用就是让obj
可以访问t.prototype
中的属性。
this.constructor = e
的作用是e.prototype.constructor
本是是指向e的,这里只是恢复一下,因为e.prototype=new r
"覆盖"了原本的 t.prototype
。
不知道你对原型链了解多少,所以就这样说了。
var __extends = function (e, t) {
function r() {
this.constructor = e
}
for (var n in t)
if (t.hasOwnProperty(n))
e[n] = t[n];
r.prototype = t.prototype;
e.prototype = new r
};
只是JS中原型链继承的一种方式
传入2个参数一个参数 e为原函数对象,t为将要继承的函数对象
function r() {
this.constructor = e
}
定义一个内部函数r,将其原型对象的的构造函数指向e,说通过new r创建的实例对象的构造函数为e,怪吧~~~下面会用到
for (var n in t)
if (t.hasOwnProperty(n))
e[n] = t[n];
上面代码的作用那个是将t的自有属性(非原型对象属性)复制到e
r.prototype = t.prototype;
将r的原型对象指向t的原型对象,此时t的原型对象的constructor属性作为t的原型对象的constructor
e.prototype = new r
将e的原型指向通过new r创建的实例对象,此时e的constructor属性就是r函数中 ‘’‘this.constructor = e’‘’ 指定的e函数对象,将在r.prototype = t.prototype;
设置的constructor属性变更指向e函数对象了
同时e能够访问到t原型中的方法及t非原型对象的属性
整个_extends函数的核心就是通过r函数作为媒介,将e和t关联起来
例子
function Car(){
this.name="car";
}
Car.attachData="CAR";
Car.prototype.play=function(){
console.log(this.name+" can play");
}
function Transformer(){
this.name="Transformer";
}
__extends(Transformer,Car);
var transformer=new Transformer();
transformer.play();
console.log(Transformer.attachData);//CAR
这函数有问题,e 的 prototype 被改变了