首页 > 这段js代码有什么作用?

这段js代码有什么作用?

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,这一句是为了实现原型链的继承。这一句之后就导致(实现这个只能通过newe.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 被改变了

【热门文章】
【热门文章】