在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ HTML/ 構(gòu)造函數(shù)
arguments 對(duì)象
類型轉(zhuǎn)換
構(gòu)造函數(shù)
instanceof 操作符
自動(dòng)分號(hào)插入
為什么不要使用 eval
對(duì)象使用和屬性
作用域與命名空間
this 的工作原理
typeof 操作符
相等與比較
閉包和引用
數(shù)組遍歷與屬性
Array 構(gòu)造函數(shù)
原型
hasOwnProperty 函數(shù)
undefined 和 null
函數(shù)聲明與表達(dá)式
setTimeout 和 setInterval
for in 循環(huán)

構(gòu)造函數(shù)

JavaScript 中的構(gòu)造函數(shù)和其它語(yǔ)言中的構(gòu)造函數(shù)是不同的。 通過(guò) new 關(guān)鍵字方式調(diào)用的函數(shù)都被認(rèn)為是構(gòu)造函數(shù)。

在構(gòu)造函數(shù)內(nèi)部 - 也就是被調(diào)用的函數(shù)內(nèi) - this 指向新創(chuàng)建的對(duì)象 Object。 這個(gè)新創(chuàng)建的對(duì)象的 prototype 被指向到構(gòu)造函數(shù)的 prototype。

如果被調(diào)用的函數(shù)沒(méi)有顯式的 return 表達(dá)式,則隱式的會(huì)返回 this 對(duì)象 - 也就是新創(chuàng)建的對(duì)象。

    function Foo() {
        this.bla = 1;
    }

    Foo.prototype.test = function() {
        console.log(this.bla);
    };

    var test = new Foo();

上面代碼把 Foo 作為構(gòu)造函數(shù)調(diào)用,并設(shè)置新創(chuàng)建對(duì)象的 prototypeFoo.prototype。

顯式的 return 表達(dá)式將會(huì)影響返回結(jié)果,但僅限于返回的是一個(gè)對(duì)象。

    function Bar() {
        return 2;
    }
    new Bar(); // 返回新創(chuàng)建的對(duì)象

    function Test() {
        this.value = 2;

        return {
            foo: 1
        };
    }
    new Test(); // 返回的對(duì)象

譯者注new Bar() 返回的是新創(chuàng)建的對(duì)象,而不是數(shù)字的字面值 2。 因此 new Bar().constructor === Bar,但是如果返回的是數(shù)字對(duì)象,結(jié)果就不同了,如下所示

    function Bar() {
        return new Number(2);
    }
    new Bar().constructor === Number

譯者注這里得到的 new Test()是函數(shù)返回的對(duì)象,而不是通過(guò)new關(guān)鍵字新創(chuàng)建的對(duì)象,因此:

    (new Test()).value === undefined
    (new Test()).foo === 1

如果 new 被遺漏了,則函數(shù)不會(huì)返回新創(chuàng)建的對(duì)象。

    function Foo() {
        this.bla = 1; // 獲取設(shè)置全局參數(shù)
    }
    Foo(); // undefined

雖然上例在有些情況下也能正常運(yùn)行,但是由于 JavaScript 中this的工作原理, 這里的 this 指向全局對(duì)象。

工廠模式

為了不使用 new 關(guān)鍵字,構(gòu)造函數(shù)必須顯式的返回一個(gè)值。

    function Bar() {
        var value = 1;
        return {
            method: function() {
                return value;
            }
        }
    }
    Bar.prototype = {
        foo: function() {}
    };

    new Bar();
    Bar();

上面兩種對(duì) Bar 函數(shù)的調(diào)用返回的值完全相同,一個(gè)新創(chuàng)建的擁有 method 屬性的對(duì)象被返回, 其實(shí)這里創(chuàng)建了一個(gè)閉包。

還需要注意, new Bar()不會(huì)改變返回對(duì)象的原型(譯者注也就是返回對(duì)象的原型不會(huì)指向 Bar.prototype)。 因?yàn)闃?gòu)造函數(shù)的原型會(huì)被指向到剛剛創(chuàng)建的新對(duì)象,而這里的 Bar 沒(méi)有把這個(gè)新對(duì)象返回(譯者注:而是返回了一個(gè)包含 method 屬性的自定義對(duì)象)。

在上面的例子中,使用或者不使用 new 關(guān)鍵字沒(méi)有功能性的區(qū)別。

譯者注上面兩種方式創(chuàng)建的對(duì)象不能訪問(wèn) Bar 原型鏈上的屬性,如下所示:

    var bar1 = new Bar();
    typeof(bar1.method); // "function"
    typeof(bar1.foo); // "undefined"

    var bar2 = Bar();
    typeof(bar2.method); // "function"
    typeof(bar2.foo); // "undefined"

通過(guò)工廠模式創(chuàng)建新對(duì)象

我們常聽(tīng)到的一條忠告是不要使用 new 關(guān)鍵字來(lái)調(diào)用函數(shù),因?yàn)槿绻浭褂盟蜁?huì)導(dǎo)致錯(cuò)誤。

為了創(chuàng)建新對(duì)象,我們可以創(chuàng)建一個(gè)工廠方法,并且在方法內(nèi)構(gòu)造一個(gè)新對(duì)象。

    function Foo() {
        var obj = {};
        obj.value = 'blub';

        var private = 2;
        obj.someMethod = function(value) {
            this.value = value;
        }

        obj.getPrivate = function() {
            return private;
        }
        return obj;
    }

雖然上面的方式比起 new 的調(diào)用方式不容易出錯(cuò),并且可以充分利用私有變量帶來(lái)的便利, 但是隨之而來(lái)的是一些不好的地方。

  1. 會(huì)占用更多的內(nèi)存,因?yàn)樾聞?chuàng)建的對(duì)象不能共享原型上的方法。
  2. 為了實(shí)現(xiàn)繼承,工廠方法需要從另外一個(gè)對(duì)象拷貝所有屬性,或者把一個(gè)對(duì)象作為新創(chuàng)建對(duì)象的原型。
  3. 放棄原型鏈僅僅是因?yàn)榉乐惯z漏 new 帶來(lái)的問(wèn)題,這似乎和語(yǔ)言本身的思想相違背。

總結(jié)

雖然遺漏 new 關(guān)鍵字可能會(huì)導(dǎo)致問(wèn)題,但這并不是放棄使用原型鏈的借口。 最終使用哪種方式取決于應(yīng)用程序的需求,選擇一種代碼書(shū)寫(xiě)風(fēng)格并堅(jiān)持下去才是最重要的。