<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                [TOC] # 揭開 constructor > 在 Javascript 語言中,`constructor` 屬性是專門為 function 而設計的,它存在于每一個 function 的`prototype` 屬性中。這個 `constructor` 保存了指向 function 的一個引用。 > 在定義一個函數(代碼如下所示)時, ~~~ function F() { // some code } ~~~ JavaScript 內部會執行如下幾個動作: > 1. 為該函數添加一個原型(`prototype`)屬性 > 2. 為 `prototype` 對象額外添加一個 `constructor` 屬性,并且該屬性保存指向函數 F 的一個引用 這樣當我們把函數 F 作為自定義構造函數來創建對象的時候,對象實例內部會自動保存一個指向其構造函數(這里就是我們的自定義構造函數 F)的 `prototype` 對象的一個屬性`__proto__`, 所以我們在每一個對象實例中就可以訪問構造函數的 `prototype` 所有擁有的全部屬性和方法,就好像它們是實例自己的一樣。當然該實例也有一個 `constructor`屬性了(從 `prototype` 那里獲得的),每一個對象實例都可以通過 `constrcutor` 對象訪問它的構造函數,請看下面代碼: ~~~ var f = new F(); alert(f.constructor === F);// output true alert(f.constructor === F.prototype.constructor);// output true ~~~ 我們可以利用這個特性來完成下面的事情: 對象類型判斷,如: ~~~ if(f.constructor === F) { // do sth with F } ~~~ 其實 `constructor` 的出現原本就是用來進行對象類型判斷的,但是**constructor 屬性易變,不可信賴**。我們有一種更加安全可靠的判定方法:`instanceof` 操作符。下面代碼,仍然返回 `true`: ~~~js if(f instanceof F) { // do sth with F } ~~~ 原型鏈繼承,由于 `constructor` 存在于 `prototype` 對象上,因此我們可以結合`constructor`沿著原型鏈找到最原始的構造函數,如下面代碼: ~~~js function Base() {} // Sub1 inherited from Base through prototype chain function Sub1(){} Sub1.prototype = new Base(); Sub1.prototype.constructor = Sub1; Sub1.superclass = Base.prototype; // Sub2 inherited from Sub1 through prototype chain function Sub2(){} Sub2.prototype = new Sub1(); Sub2.prototype.constructor = Sub2; Sub2.superclass = Sub1.prototype; // Test prototype chain alert(Sub2.prototype.constructor);// function Sub2(){} alert(Sub2.superclass.constructor);// function Sub1(){} alert(Sub2.superclass.constructor.superclass.constructor);// function Base(){} ~~~ 上面的例子只是為了說明`constructor`在原型鏈中的作用,更實際一點的意義在于:**一個子類對象可以獲得其父類的所有屬性和方法,稱之為繼承。** 之前提到`constructor 易變`,那是因為函數的 `prototype` 屬性容易被更改,我們用時下很流行的編碼方式來說明問題,請看下面的示例代碼: ~~~ function F() {} F.prototype = { _name: 'Eric', getName: function() { return this._name; } }; // 初看這種方式并無問題,但是你會發現下面的代碼失效了 var f = new F(); console.log(f.constructor === F); // output false ~~~ 怎么回事?F 不是實例對象 f 的構造函數了嗎?當然是!只不過構造函數 F 的原型被開發者重寫了,這種方式將原有的 `prototype` 對象用一個對象的字面量`{}`來代替。而新建的對象`{}`只是 Object 的一個實例,系統(或者說瀏覽器)在解析的時候并不會在`{}`上自動添加一個 `constructor` 屬性,因為這是 `function` 創建時的專屬操作,僅當你聲明函數的時候解析器才會做此動作。然而你會發現 `constructor` 是存在的,可以 測試它的存在性: ~~~ alert(typeof f.constructor == 'undefined');// output false ~~~ 既然存在,那這個 `constructor` 是從哪兒冒出來的呢? 因為`{}`是創建對象的一種簡寫,所以`{}`相當于是 `new Object()`。 那既然`{}`是 `Object` 的實例,自然而然他獲得一個指向構造函數 `Object()`的 `prototype` 屬性的一個引用`__proto__`,又因為 `Object.prototype` 上有一個指向 `Object` 本身的 `constructor`屬性。所以可以看出這個`constructor`其實就是`Object.prototype`的`constructor`, 下面代碼可以驗證其結論: ```js console.log(f.constructor === Object.prototype.constructor);//output true console.log(f.constructor === Object);// also output true ``` 一個解決辦法就是手動恢復它的 `constructor`,下面代碼非常好地解決了這個問題: ```js function F() {} F.prototype = { constructor: F, /* reset constructor */ _name: 'Eric', getName: function() { return this._name; } }; ``` 之后,`constructor` 重新獲得的構造函數的引用,測試上面的代碼 ```js var f = new F(); alert(f.constructor === F); // output true this time ^^ ``` # **解惑:構造函數上怎么還有 constructor ?是哪兒來的?** 細心的會發現,像 JavaScript 內建的構造函數,如 Array, RegExp, String,Number, Object, Function 等等居然自己也有一個 constructor: ```js alert(typeof Array.constructor != 'undefined');// output true ``` 經過測試發現,此物非彼物它和 `prototype` 上 `constructor` 不是同一個對象,他們是共存的: ```js alert(typeof Array.constructor != 'undefined');// output true alert(typeof Array.prototype.constructor === Array); // output true ``` 不過這件事情也是好理解的,因為 構造函數也是函數。說明它就是 Function 構造函數的實例對象,自然它內部也有一個指向 `Function.prototype` 的內部引用`__proto__`啦。因此我們很容易得出結論,這個 `constructor`(構造函數上的`constructor` 不是 `prototype` 上的)其實就是**Function 構造函數的引用**: ```js console.log(Array.constructor === Function);// output true console.log(Function.constructor === Function); // output true ``` # 問? ## 任何對象都有`constructor`屬性,不僅僅存在于function 的prototype 屬性中? * **回復:** 你要知道其他對象的`constructor`屬性是從哪里來的,就比如 ```js var a = {}; a.constructor === Object` ``` 這里面 `a` 的 `constructor` 屬性是從哪里來的,是 js 默認添加的嗎,顯然不是,`a = {}`可以看成是通過`a = new Object()`,實例化之后`a`會有一個`__proto__`屬性,它指向它的構造函數的`prototype`,`a`本身是沒有 `constructor` 這個屬性的,它就會去它的構造函數的`prototype`中去找,而 `Object` 的 `prototype` 中有`constructor`這個屬性,且指向本身,所有你才可以看到`a.constructor === Object` ## **為什么要設置prototype.constructor?** 每次實現JS的繼承時,代碼里必有如下兩句: ~~~javascript // 用于設置原型 Employee.prototype = new Person() // 設置原型的構造器 Employee.prototype.constructor=Employee ~~~ 實現原型鏈就靠第一句話,但第二句話有什么用呢? * **回復:** 即使不做這樣的修正也不會有什么影響,它**主要防止一種情況下出錯,就是你顯式地去使用構造函數**。 比如,我并不知道`woman`是由哪個函數實例化出來的,但是我想 clone 一個,這時就可以這樣: ~~~ var woman = new Woman(); ... var woman1 = woman.constructor(); ~~~ # 參考 [為什么要做A.prototype.constructor=A這樣的修正?](https://www.cnblogs.com/SheilaSun/p/4397918.html) http://stackoverflow.com/questions/8453887/why-is-it-necessary-to-set-the-prototype-constructor
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看