JavaScript創(chuàng)建對象方式及性能問題

通過Object構(gòu)造函數(shù)或者字面量創(chuàng)建對象

    var obj01 = new Object();
    var obj02 = {};
  • 弊端:無論通過Object來創(chuàng)建對象, 還是通過字面量來創(chuàng)建對象都存在一個弊端,每次創(chuàng)建都需要重新編寫一次, 如果創(chuàng)建的多個對象的屬性和方法名稱一樣赤惊,浪費時間

通過工廠函數(shù)創(chuàng)建對象

//所以我們可以通過工廠函數(shù)來創(chuàng)建對象
     */
    // 工廠函數(shù)
    function createPerson(name, age) {
        // 1.通過Object創(chuàng)建一個空對象
        // var obj = new Object();
        var obj = {};
        // 2.動態(tài)的給空對象添加屬性和方法
        obj.name = name;
        obj.age = age;
        obj.say = function () {
            console.log("hello");
        };
        // 3.將函數(shù)中創(chuàng)建的對象返回給調(diào)用者
        return obj;
    }
    var obj1 = createPerson("luodou", 13);
    var obj2 = createPerson("doudou", 18);
    console.log(obj1);
    console.log(obj2);

    console.log(typeof obj1); // object
    console.log(obj1.constructor); // ? Object() { [native code] }
  • 工廠函數(shù)實質(zhì)上是Object或字面量創(chuàng)建對象的封裝,調(diào)用函數(shù)即可創(chuàng)建對象
  • 弊端:通過Object對象, 或者通過字面量, 或者通過工廠函數(shù)創(chuàng)建的對象, 我們無法判斷這個對象是誰創(chuàng)建出來的凰锡,代碼最后一行constructor指向的是一個Object

通過構(gòu)造函數(shù)創(chuàng)建對象

  • 什么是構(gòu)造函數(shù)?

    • 構(gòu)造函數(shù)也是一個函數(shù), 只不過是專門用于創(chuàng)建對象的函數(shù)而已
  • 構(gòu)造函數(shù)和普通函數(shù)的區(qū)別?

    • 構(gòu)造函數(shù)的函數(shù)名稱首字母必須大寫
    • 構(gòu)造函數(shù)必須使用new 來調(diào)用
  • 構(gòu)造函數(shù)本質(zhì)上是對工廠函數(shù)的簡化

    • 在構(gòu)造函數(shù)中默認會創(chuàng)建一個空的對象, 會將創(chuàng)建的對象賦值給this,會將創(chuàng)建的對象返回給調(diào)用者
  • 過去通過Object對象, 或者通過字面量, 或者通過工廠函數(shù)創(chuàng)建的對象, 我們無法判斷這個對象是誰創(chuàng)建出來的,但是通過構(gòu)造函數(shù)創(chuàng)建的對象, 我們可以判斷這個對象是誰創(chuàng)建出來的(見代碼里obj.constructor)

  • 默認情況下每一個對象都有一個隱藏的屬性, 叫做constructor, 這個屬性指向了創(chuàng)建當前對象的構(gòu)造函數(shù)

    // 1.自定義一個構(gòu)造函數(shù)
    function Person(name, age) {
        // 1.var obj = new Object();
        // 2.this = obj;
        this.name = name; // obj.name = name;
        this.age = age;
        this.say = function () {
            console.log("hello");
        }
        // 3.return obj;
    }
    /*
    new Person("luodou", 13);做了什么事情?
    1.會在構(gòu)造函數(shù)中創(chuàng)建一個空的對象
    2.將創(chuàng)建好的空對象賦值給this
    3.將創(chuàng)建好的對象返回給調(diào)用者
     */
    var obj = new Person("luodou", 13);
    console.log(obj);

    console.log(typeof obj); // object
    console.log(obj.constructor); // ? Person(name, age) {}

    // 判斷obj對象是否是Person構(gòu)造函數(shù)創(chuàng)建出來的
    // console.log(obj.constructor === Person); // 不推薦

    // 如果想判斷某個對象時候是某個構(gòu)造函數(shù)創(chuàng)建出來的
    // 可以使用 對象名稱 instanceof 構(gòu)造函數(shù)名稱, 來判斷
    console.log(obj instanceof Person); // true


    function Student(name, age, score) {
        this.name = name; // obj.name = name;
        this.age = age;
        this.score = score;
    }
    var obj2 = new Student("dou", 11, 99);
    console.log(obj2 instanceof Person);  //false
    console.log(obj2 instanceof Student); //true
  • 弊端:默認情況下, 只要創(chuàng)建一個對象就會在對象中開辟一塊存儲空間未舟,該存儲空間中會存儲對象的所有數(shù)據(jù),浪費空間
    function Person(name, age) {
        this.name = name;
        this.age = age;
        this.say = function () {
            //           obj1.name, obj1.age
            //           obj2.name, obj2.age
            console.log(this.name, this.age);
        };
    }
    var obj1 = new Person("lnj", 13);
    obj1.say();

    var obj2 = new Person("zq", 18);
    obj2.say();

    // 這里的===是在判斷兩個函數(shù)的地址是否相同
    console.log(obj1.say === obj2.say);  //false
  • 解決方案:
    • 將方法定義在外面, 將定義在外面函數(shù)的地址賦值給屬性掂为,每次創(chuàng)建對象, 對象中say保存的都是函數(shù)的地址, 就不會重復(fù)保存了
    /*
    注意點: 在JavaScript中, 函數(shù)也是一個對象
     */
    function say() {
        console.log(this.name, this.age);
    }
    // var say = function () {
    //     console.log(this.name, this.age);
    // };
    // var say = new Function("console.log(this.name, this.age);");

    // 定義了一個構(gòu)造函數(shù)
    function Person(name, age) {
        this.name = name;
        this.age = age;
        this.say = say;
    }

    var obj1 = new Person("luodou", 13);
    obj1.say();

    var obj2 = new Person("dou", 18);
    obj2.say();

    // 這里的===是在判斷兩個函數(shù)的地址是否相同
    console.log(obj1.say === obj2.say); // true
  • 弊端:因為將函數(shù)定義在了全局作用域中, 所以如果定義了多個函數(shù), 會導(dǎo)致全局作用域的名稱匱乏

  • 解決方案2.0

    • 將所有函數(shù)都封裝到另外一個對象中, 這樣函數(shù)名稱就不在全局作用域中了, 這就不會導(dǎo)致全局作用域命名匱乏問題了裕膀,然后將對象中方法的地址復(fù)制給使用者即可
    var fns = {
        say: function() {
            console.log(this.name, this.age);
        },
        eat: function () {
        console.log("eat");
        }
    };

    // 定義了一個構(gòu)造函數(shù)
    function Person(name, age) {
        this.name = name;
        this.age = age;

        this.say = fns.say;
        this.eat = fns.eat;
    }

    var obj1 = new Person("luodou", 13);
    obj1.say();

    var obj2 = new Person("dou", 18);
    obj2.say();

    // 這里的===是在判斷兩個函數(shù)的地址是否相同
    console.log(obj1.say === obj2.say); // true

終極解決方案

前面的通通忘掉!

  • 在JavaScript中,每一個構(gòu)造函數(shù)都有一個默認的屬性, 這個屬性叫做prototype,prototype屬性指向一個對象, 這個對象我們稱之為構(gòu)造函數(shù)的原型對象

  • 既然構(gòu)造函數(shù)的prototype就對應(yīng)一個對象, 所以我們就可以將方法都放到這個對象中

  • 注意點:所有通過同一個構(gòu)造函數(shù)創(chuàng)建出來的對象, 都可以訪問該構(gòu)造函數(shù)的原型對象勇哗,并且所有通過同一個構(gòu)造函數(shù)創(chuàng)建出來的對象, 訪問的都是同一個原型對象

    // 定義了一個構(gòu)造函數(shù)
    function Person(name, age) {
        this.name = name;
        this.age = age;
    }
    /*
    私有成員(一般就是非函數(shù)成員)放到構(gòu)造函數(shù)中
    共享成員(一般就是函數(shù))放到原型對象中
    如果重置了 prototype 記得修正 constructor 的指向
     */
    Person.prototype.say = function () {
        console.log(this.name, this.age);
    };

    // console.log(Person.prototype);

    var obj1 = new Person("luodou", 13);
    obj1.say();

    var obj2 = new Person("dou", 18);
    obj2.say();

    // 這里的===是在判斷兩個函數(shù)的地址是否相同
    console.log(obj1.say === obj2.say); // true
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末昼扛,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子欲诺,更是在濱河造成了極大的恐慌抄谐,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,681評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件扰法,死亡現(xiàn)場離奇詭異蛹含,居然都是意外死亡,警方通過查閱死者的電腦和手機塞颁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,205評論 3 399
  • 文/潘曉璐 我一進店門浦箱,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人祠锣,你說我怎么就攤上這事酷窥。” “怎么了伴网?”我有些...
    開封第一講書人閱讀 169,421評論 0 362
  • 文/不壞的土叔 我叫張陵蓬推,是天一觀的道長。 經(jīng)常有香客問我澡腾,道長拳氢,這世上最難降的妖魔是什么募逞? 我笑而不...
    開封第一講書人閱讀 60,114評論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮馋评,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘刺啦。我一直安慰自己留特,他們只是感情好,可當我...
    茶點故事閱讀 69,116評論 6 398
  • 文/花漫 我一把揭開白布玛瘸。 她就那樣靜靜地躺著蜕青,像睡著了一般。 火紅的嫁衣襯著肌膚如雪糊渊。 梳的紋絲不亂的頭發(fā)上右核,一...
    開封第一講書人閱讀 52,713評論 1 312
  • 那天,我揣著相機與錄音渺绒,去河邊找鬼贺喝。 笑死,一個胖子當著我的面吹牛宗兼,可吹牛的內(nèi)容都是我干的躏鱼。 我是一名探鬼主播,決...
    沈念sama閱讀 41,170評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼殷绍,長吁一口氣:“原來是場噩夢啊……” “哼染苛!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起主到,我...
    開封第一講書人閱讀 40,116評論 0 277
  • 序言:老撾萬榮一對情侶失蹤茶行,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后登钥,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體畔师,經(jīng)...
    沈念sama閱讀 46,651評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,714評論 3 342
  • 正文 我和宋清朗相戀三年怔鳖,在試婚紗的時候發(fā)現(xiàn)自己被綠了茉唉。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,865評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡结执,死狀恐怖度陆,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情献幔,我是刑警寧澤懂傀,帶...
    沈念sama閱讀 36,527評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站蜡感,受9級特大地震影響蹬蚁,放射性物質(zhì)發(fā)生泄漏恃泪。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,211評論 3 336
  • 文/蒙蒙 一犀斋、第九天 我趴在偏房一處隱蔽的房頂上張望贝乎。 院中可真熱鬧,春花似錦叽粹、人聲如沸览效。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,699評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽锤灿。三九已至,卻和暖如春辆脸,著一層夾襖步出監(jiān)牢的瞬間但校,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,814評論 1 274
  • 我被黑心中介騙來泰國打工啡氢, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留状囱,地道東北人。 一個月前我還...
    沈念sama閱讀 49,299評論 3 379
  • 正文 我出身青樓空执,卻偏偏與公主長得像浪箭,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子辨绊,可洞房花燭夜當晚...
    茶點故事閱讀 45,870評論 2 361