使用`prototype`而不是`this`的原因

时间:2012-06-09 10:25:37

标签: javascript

我正在使用Lightbox2

https://github.com/lokesh/lightbox2/blob/master/js/lightbox.js

我不明白为什么Lightbox的所有内部成员都是原型(Lightbox.prototype.init),而不仅仅是成员(Lightbox.init)?

如果它们特定于每个灯箱实例,那么使用this.init会不会更容易?

2 个答案:

答案 0 :(得分:8)

困惑?不要......

这样想:

  1. Lightbox是你的类定义,但它还不是一个实例。

  2. 无论你直接在课堂上放什么就像一个静态成员:

    Lightbox.staticFunc = function() {
        // "this" will not point to instance object
    };
    
  3. 无论你在原型上放置什么,都是一个共享的实例成员:

    Lightbox.prototype.instanceFunc = function() {
        // "this" will point to object instance so members can be accessed
    };
    
  4. 创建类的实例时,所有实例成员都可以通过this关键字访问,但是通过类定义可以访问静态实例:

    var someData = Lightbox.staticFunc();
    var l = new Lightbox();
    l.instanceFunc();
    
  5. 这是否清楚了解原型成员?

    灯箱代码

    您一直在寻找的代码意味着:

    // this is a constructor that accesses instance properties (using "this")
    // ------
    // since properties are accessed via "this.something" means that they are
    //    not shared between instances but are part of one particular instance
    // ------
    function Lightbox(options) {
        this.options = options;
        this.album = [];
        this.currentImageIndex = void 0;
        this.init();
    }
    
    // adding an instance method that will be accessible to lightbox object instance
    //    that's why it can also access instance members (using "this")
    // ------
    // all functions that are defined on the prototype are shared between
    //    all instances so they consume less resources because not every
    //    object instance created them separately.
    // ------
    Lightbox.prototype.init = function() {
        this.enable();
        return this.build();
    };
    

    但是这段代码的某些部分有点令人困惑,即

    LightboxOptions = (function() {
    
        function LightboxOptions() {
            this.fileLoadingImage = 'images/loading.gif';
            this.fileCloseImage = 'images/close.png';
            this.resizeDuration = 700;
            this.fadeDuration = 500;
            this.labelImage = "Image";
            this.labelOf = "of";
        }
    
        return LightboxOptions;
    
    })();
    

    LightboxOptions类包含在函数闭包中,即使它没有定义任何私有数据,因此在此示例中可以省略外部立即执行的函数,同时具有相同的结果:

    LightboxOptions = function() {
        this.fileLoadingImage = 'images/loading.gif';
        this.fileCloseImage = 'images/close.png';
        this.resizeDuration = 700;
        this.fadeDuration = 500;
        this.labelImage = "Image";
        this.labelOf = "of";
    };
    

    当然可以使用this在构造函数中定义这些函数,但之后它们不会在实例之间共享,因此每个对象实例都会定义相同的函数,从而消耗更多资源。所以这不一样,虽然从执行点来看它看起来一样:

    CustomClass = function() {
        this.prop = true;
    };
    CustomClass.prototype.method = function() { alert("I'm shared."); };
    

    略有不同:

    CustomClass = function() {
        this.prop = true;
        this.method = function() { alert("I'm duplicated in every instance."); };
    };
    

    后者在为每个对象实例定义函数时消耗更多资源。

    ......还有一点要完全清除这件事

    假设我们有这个类定义:

    var C = function() {
        this.prop = true;
        this.method = function() { console.log("Per instance method"); };
    }
    C.prototype.method = function() { console.log("Shared instance method"); };
    

    如果我们调用这些代码行

    ,会发生什么
    var a = new C();
    var b = new C();
    a.method();
    b.method();
    delete a.method;
    a.method();
    b.method();
    

    您认为产量是多少?您应该至少对delete之后发生的事情感到困惑?哪种方法会被删除?每个实例?共享?都?因为它应该是每个实例方法在对象实例a上被删除,这就是为什么之后它报告已经调用了共享方法的原因。但仅限于ab仍然有自己的每个实例方法。

    所以没有任何进一步的麻烦,输出如下:

    Per instance method      // a.method
    Per instance method      // b.method
    Shared instance method   // a.method
    Per instance method      // b.method
    

    prototype属性

    怎么样?

    这些是不同的。创建对象实例时,所有这些属性都将复制到每个对象,并且不会共享。所以无论你在特定物体范围内对​​它们做什么都不会反映给别人。

    如果你在某个特定对象上删除了这样的属性,那么它的初始值仍然可用,就像对象被实例化时一样。

    var C = new function() {};
    C.prototype.prop = 1;
    
    var a = new C();
    var b = new C();
    
    a.prop = 10;   // does not change the value of "b.prop"
    delete a.prop; // "a.prop" is now back to 1
    

答案 1 :(得分:4)

  

如果它们特定于灯箱的每个实例都不会   更容易使用this.init?

他们不应该这就是为什么他们把所有东西放在prototype对象中。当您使用prototype时,只有当他们不成为实例成员时,所有方法仍然可用。

JavaScript使用原型链,当它看到一个方法时,它会搜索原型链,直到找到指定的方法。如果在中间找不到最终的Object对象,则此过程将持续到该对象。

您应该只创建您认为合理或需要的实例成员(通过this),因为如果您使用this关键字(例如实例成员)放置不必要的方法,则会增加开销(计算浪费)。 / p>

相关问题