精品伊人久久大香线蕉,开心久久婷婷综合中文字幕,杏田冲梨,人妻无码aⅴ不卡中文字幕

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
創(chuàng)建對象及原型
一、使用Object構造函數(shù)或對象字面量創(chuàng)建對象
  缺點:使用同一個接口創(chuàng)建對象,會產(chǎn)生大量的重復性代碼。
  解決方法:使用工廠模式創(chuàng)建對象。
1 //構造函數(shù)2 let obj1 = new Object();3 obj1.name = '我和鴿子有個約會';4 obj1.age = 22;5 //字面量6 let obj2 = {7    name: '我和鴿子有個約會',8    age: 22,9  };
二、使用工廠模式創(chuàng)建對象
核心思想:創(chuàng)建一種函數(shù),用函數(shù)來封裝以特定接口創(chuàng)建對象的細節(jié)。
優(yōu)點:
createPerson()可以根據(jù)接收來的三個參數(shù)來構建一個包含所有必要信息的person對象。
     可以無數(shù)次地調(diào)用這個函數(shù),每次都能返回一個包含三個屬性和一個方法的對象。

     這樣就解決了創(chuàng)建多個相似對象,產(chǎn)生大量重復代碼的問題。
缺點:
    無法識別對象的類型,比如:我們想創(chuàng)建一個person類型(人類)的對象和cat類型(貓類)的對象,
    但是我們無法將它們區(qū)分開來,因為它們本質(zhì)上都是通過Object構造函數(shù)創(chuàng)建的。

解決方法:構造函數(shù)模式
 1 function createPerson(name, age, job) { 2         let obj = new Object(); 3         obj.name = name; 4         obj.age = 22; 5         obj.job = job; 6         obj.sayName = function () { 7             console.log(this.name); 8         }; 9         return obj;10     }11 12 let person1 = createPerson('鴿子1', 22, 'programmer');13 let person2 = createPerson('鴿子2', 20, 'student');14 let cat = createPerson('貓', 3, 'Catch mice');
三、構造函數(shù)模式
  ECMAScript中的構造函數(shù)可以用來創(chuàng)建特定類型的對象,像Object、Array這樣的原生構造函數(shù),在運行時會自動出現(xiàn)在
  執(zhí)行環(huán)境中,
所以我們可以直接使用它們創(chuàng)建Object或者Array類型的對象。
  當然,我們也可以自定義構造函數(shù),從而定義自定義對象類型的屬性和方法。

自定義構造函數(shù)與工廠模式中的函數(shù)的不同:
1.沒有顯示地創(chuàng)建對象;
2.直接將屬性和方法賦給了this對象;
3.沒有return語句
4.函數(shù)名首字母大寫,不是硬性要求只是一種規(guī)范,目的是為了將構造函數(shù)和普通函數(shù)區(qū)分開來,
      因為構造函數(shù)也是函數(shù),只不過它可以用來創(chuàng)建對象而已。


    使用構造函數(shù)創(chuàng)建對象這一行為,被稱為該構造函數(shù)的實例化(類的實例),其對象被稱為構造函數(shù)的實例或實例對象。
    構造函數(shù)與其它函數(shù)的唯一區(qū)別就在于調(diào)用它們的方式不同。任何函數(shù),只要通過new操作符調(diào)用,那它就是構造函數(shù),
    如果不通過new操作符來調(diào)用,那和普通函數(shù)沒什么區(qū)別。


  注意:
使用構造函數(shù)創(chuàng)建對象需要使用 new 操作符。
這種方式調(diào)用構造函數(shù)實際上會經(jīng)歷以下4個步驟:
1.創(chuàng)建一個空對象;
2.將構造函數(shù)的作用域賦給新對象(因此this就指向了這個新對象);
3.執(zhí)行構造函數(shù)中的代碼(為這個新對象添加屬性);
4.返回新對象。

  缺點:
所有方法都要在每個實例上重新創(chuàng)建一遍。
例如:person3和person4中的sayName()方法,雖然它們同屬于Person的實例,但其中的方法是獨立的,
     也就是說,每實例化一個對象,都會在該對象中創(chuàng)建一個新的方法,這樣十分損耗性能。

  解決方法:
1.將函數(shù)定義到構造函數(shù)外面,這樣每個實例對象中的方法都是同一個方法。
 1 function Person(name, age, job) { 2       this.name = name; 3       this.age = age; 4       this.job = job; 5       this.sayName = sayName; 6     } 7  function sayName() { 8        console.log(this.name); 9       }10  console.log(person3.sayName === person4.sayName); //true 說明兩個實例對象中的方法是同一個
        但這樣也有一個缺點:污染命名空間,比如一個構造函數(shù)有好多方法,就要定義好多變量,代碼多了就
        有可能出現(xiàn)重名的情況。

2.使用原型模式
四、原型模式
    每個函數(shù)都有一個prototype(原型)屬性,該屬性是一個指針,指向一個對象,而這個對象的用途是包含由構造
    函數(shù)創(chuàng)建的所有實例對象共享的屬性和方法。

    優(yōu)點:
      可以讓所有實例對象共享它所包含的屬性和方法。換句話說,不必在構造函數(shù)中定義實例對象的信息,可以將
      這些信息直接添加到原型對象中,這樣每個實例對象就能共用一個函數(shù)了,并且也不會污染命名空間。
 1     function Person() { 2     } 3  4     Person.prototype.name = '鴿子1'; 5     Person.prototype.age = 22; 6     Person.prototype.job = 'programmer'; 7     Person.prototype.sayName = function () { 8         console.log(this.name); //鴿子1 9     };10     let person5 = new Person();11     let person6 = new Person();12     person5.sayName();13     person6.sayName();14     console.log(person5.sayName === person6.sayName); //true
4.1 原型對象
在創(chuàng)建函數(shù)的時候,系統(tǒng)會為該函數(shù)創(chuàng)建一個prototype指針,這個指針指向的對象被稱為原型對象。
每個原型對象中都有一個constructor(構造函數(shù))屬性,該屬性也是一個指針,指向其對應的構造函數(shù)。
每個實例對象中有兩個指針: constructor(指向其構造函數(shù)) __proto__(指向其構造函數(shù)的原型對象)
1 console.log(person5.__proto__ === Person.prototype); //true2 console.log(person5.constructor === Person); //true
兩個方法:
A.prototype.isProtypeof(B)
判斷實例對象B中是否存在一個指針,指向構造函數(shù)A的原型對象,是返回true,否返回false,
     因為實例對象中有一個指針指向其構造函數(shù)的原型對象,所以我們可以間接的判斷B是不是A的實例對象。
Object.getPrototypeOf(obj) 返回實例對象的原型對象
1  console.log(Person.prototype.isPrototypeOf(person5));//true2  console.log(Object.getPrototypeOf(person5) === Person.prototype); //true3  console.log(Object.getPrototypeOf(person5).name); //鴿子1
代碼讀取實例對象屬性的過程:
  每當代碼讀取某個對象的某個屬性時,都會先在實例對象中查找該屬性,如果查找到,則返回該屬性的值;如果沒找到,
  則去往該對象的原型對象中查找,如果找到了,則返回該屬性的值。也就是說,在我們通過person5調(diào)用sayName方法
  時,會先后執(zhí)行兩次搜索,第一次是在person5對象中,第二次是在person5的原型對象中。當我們通過person6調(diào)用
  sayName方法時,會重現(xiàn)相同的搜索過程,這正是多個實例對象共享原型對象中保存的屬性和方法的基本原理。

  
  注意:
    雖然可以通過實例對象訪問其原型對象中的值,但是卻不能通過實例對象重寫原型中的值。如果我們在實例對象中添
    加一個屬性,并且該屬性與實例對象的原型中的一個屬性同名,那么該屬性就會將原型中的同名屬性屏蔽,換句話說,
    添加這個屬性只會阻止我們訪問原型中的那個屬性,而不會修改那個屬性,因為代碼讀取對象屬性的時候,首先會在
    該對象中查找,查找到就不再搜索其原型中的屬性了。
1 console.log(person5.name);// 鴿子1  name來自原型對象2 person5.name = '兔子'; //將原型中的name屬性屏蔽3 console.log(person5.name);// 兔子  name來自實例對象
in 操作符
  語法: 'name' in obj
  判斷是否可以通過對象obj訪問到name屬性,可以則返回true,否則返回false,無論是該屬性存在于實例中還是
  原型中。

hasOwnProperty()方法
語法:obj.hasOwnProperty('name')
判斷對象obj【自身中】是否含有name屬性,有則返回true,無則返回false
該方法用于檢測某屬性是存在于實例對象中還是原型對象中,只有給定屬性存在于實例對象中,才會返回true。
1     console.log('name' in person6);//true2     console.log(person5.hasOwnProperty('name'));//true3     console.log(person6.hasOwnProperty('name'));//false4     //創(chuàng)建一個函數(shù)判斷一個屬性到底是存在于對象中,還是存在于其原型中5     function hasPrototypeProperty(object, name) {6         return !object.hasOwnProperty(name) && name in object;//返回false則表示存在于對象中,返回true表示存在于原型中7     }8 9     hasPrototypeProperty(person5, 'name');//false
4.2.更簡單的原型語法
    上面例子中,每給原型對象添加一個屬性或方法就要敲一遍Person.prototype。
    為減少代碼量,也為了從視覺上更好地封裝原型的功能,更常見的做法是用一個包含所有屬性和方法的字面量對
    象來重寫整個原型對象。
 1     function Person() { 2  3     } 4  5     Person.prototype = { 6         name: '鴿子1', 7         age: 22, 8         job: 'programmer', 9         sayName: function () {10             console.log(this.name);11         },12     };13     console.log(Person.prototype.constructor === Person);//false
注意:
  上面的代碼中,我們將Person.prototype指向一個新的對象,雖然結果相同,但有一個例外:
  該原型對象的constructor屬性不再指向Person了,而是指向Object。

  這是因為每創(chuàng)建一個函數(shù),都會生成一個prototype屬性指向它的原型對象,并且該原型對象有一個constructor
  屬性指向這個函數(shù),然而,Person.prototype = {},本質(zhì)上是將prototype屬性指向一個新的對象,而這個新對
  象的構造函數(shù)是Object。

  如果constructor的值真的很重要,我們可以手動改回來
 1   Person.prototype = { 2         constructor: Person,//手動更改原型對象中的constructor指向 3          name: '鴿子1', 4          age: 22, 5          job: 'programmer', 6          sayName: function () { 7             console.log(this.name); 8          }, 9      };10   console.log(Person.prototype.constructor === Person);//true


4.3 原型的動態(tài)性
  因為在原型中查找值的過程是一次搜索,因此我們對原型對象的任何修改都能夠立即從實例上反映出來,即使是先創(chuàng)
  建了實例后修改原型也是如此。
  就像下邊的例子:
    雖然friend實例是在新方法之前創(chuàng)建的,但是它仍能訪問到這個新方法,其原因可以歸結為實例與原型之間的
    松散連接關系。
當我們調(diào)用friend.sayHello()方法時,首先會在friend對象中搜索sayHello屬性,在沒
    找到的情況下,會繼續(xù)搜索原型。
1     let friend = new Person();2     Person.prototype.sayHello = function () {3         console.log('hello');4     };5     friend.sayHello();//hello
注意:
  盡管可以隨時為原型添加屬性和方法,并且修改能夠立即在對象實例中反映出來,但是如果重寫整個原型對象,那么
  情況就不一樣了。
  
因為調(diào)用構造函數(shù)時會為實例添加一個指向最初原型的指針__proto__,而把原型修改為另一個對象就等于切斷了
  構造函數(shù)與原型之間的聯(lián)系。
 1  function Person() { 2     } 3  4  let person7 = new Person(); 5  Person.prototype = { 6       constructor: Person, 7       gugugu: '鴿子', 8   }; 9  console.log(person7.gugugu);//undefined10  console.log(person7.__proto__ === Person.prototype);//false

原型模式的缺點:
  1.我們通過上面的例子可以發(fā)現(xiàn),它省略了為構造函數(shù)傳遞初始化參數(shù)這一環(huán)節(jié),結果所有實例對象在默認情況下都
   將取得相同的屬性值。

  2.原型模式最大的問題是由原型對象共享的特性所導致的。

  原型中所有屬性是被多個實例所共享的,這種共享對于函數(shù)非常適合,對于那些包含基本數(shù)據(jù)類型值的屬性倒也說的
  過去,畢竟,通過在實例上添加一個同名屬性,就可以隱藏原型中對應的屬性。然而,對于包含引用類型值的屬性來說,
  這個問題就比較突出了。
 1     function Animal() { 2  3     } 4  5     Animal.prototype = { 6         constructor: Animal, 7         name: '鴿子', 8         friends: ['貓咪', '大黃', '二哈'], 9     };10     let animal1 = new Animal();11     let animal2 = new Animal();12     animal1.friends.push('小白');13     console.log(animal1.friends);//['貓咪', '大黃', '二哈','小白']14     console.log(animal2.friends);//['貓咪', '大黃', '二哈','小白']15     console.log(animal1.friends === animal2.friends);//true
從上面的代碼中,我們就能看出問題:
  當我們修改了animal1.friends引用的數(shù)組,向該數(shù)組中添加了一個字符串'小白'。由于friends數(shù)組存在于
  Animal.prototype而非animal1中,所以剛才的修改也會通過animal2.friends(因為animal1.friends
  和animal2.friends指向同一個數(shù)組)反映出來。
  假如我們的初衷就是像這樣所有實例共享一個數(shù)組,那沒什么問題,但是實例一般都是要有屬于自己的全部屬性的,
  所以很少有人會單獨使用原型模式。


  解決方法:組合使用構造函數(shù)模式和原型模式
五、組合使用構造函數(shù)模式和原型模式
  創(chuàng)建自定義類型的最常見的方式,就是組合使用構造函數(shù)模式和原型模式,構造函數(shù)模式用于定義每個實例獨立的屬
  性,而原型模式用于定義方法和共享的屬性。


  優(yōu)點:
    1.每個實例都會有自己的一份實例屬性副本,但同時又能共享者對方法的引用,最大限度地節(jié)省了內(nèi)存;
    2.支持向構造函數(shù)傳遞參數(shù)
 1     function Animal(name, age, job) { 2         this.name = name; 3         this.age = age; 4         this.job = job; 5         this.friends = ['貓咪', '大黃', '二哈']; 6     } 7  8     Animal.prototype.sayName = function () { 9         console.log(this.name);10     };11     let animal3 = new Animal('鴿子', 3, 'gugugu');12     let animal4 = new Animal('大白鵝', 2, 'gugugu');13     animal3.sayName();14     animal4.sayName();15     animal3.friends.push('小白');16     console.log(animal3.friends);//['貓咪', '大黃', '二哈','小白']17     console.log(animal4.friends);//['貓咪', '大黃', '二哈']18     console.log(animal3.friends === animal4.friends);//false



作者:我和鴿子有個約會
本文版權歸作者和博客園共有,歡迎轉載,但未經(jīng)作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。

本站僅提供存儲服務,所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權內(nèi)容,請點擊舉報
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
JS學習筆記 原型鏈和利用原型實現(xiàn)繼承
徹底理解JavaScript原型
徹底弄懂 JS 原型與繼承
詳解Javascript中prototype屬性(推薦)
JavaScript中的對象,如何創(chuàng)建對象,創(chuàng)建對象的7種模式
javascript構造函數(shù),原型和繼承的理解
更多類似文章 >>
生活服務
分享 收藏 導長圖 關注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服

主站蜘蛛池模板: 安仁县| 尼玛县| 榕江县| 山阳县| 无棣县| 西林县| 白朗县| 都安| 青岛市| 新营市| 舒兰市| 龙游县| 平和县| 政和县| 泉州市| 休宁县| 兴文县| 长顺县| 邻水| 阳信县| 交口县| 大同市| 专栏| 西和县| 城固县| 平乐县| 威信县| 盈江县| 海口市| 德兴市| 北票市| 酒泉市| 乡宁县| 彰化县| 始兴县| 繁昌县| 财经| 梅州市| 固安县| 永福县| 翼城县|