日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

重学《JavaScript 高级程序设计》笔记 第6章对象

發(fā)布時(shí)間:2023/12/10 javascript 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 重学《JavaScript 高级程序设计》笔记 第6章对象 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

第6章 面向?qū)ο蟮某绦蛟O(shè)計(jì)

ECMAScript中沒有類的概念;

1.創(chuàng)建對(duì)象-歷史

1.1 創(chuàng)建實(shí)例,添加方法和屬性 → 對(duì)象字面量

缺點(diǎn): 使用同一接口創(chuàng)建很多對(duì)象,產(chǎn)生大量重復(fù)代碼

var person = new Object() person.name = "Y" person.age = 18 person.job = "police"person.sayName = function() {alert(this.name) }

var person = {name = "Y",age = 18,job = "police",sayName = function() {alert(this.name)} }

1.2 工廠模式 (返回對(duì)象)

缺點(diǎn): 沒有解決對(duì)象識(shí)別的問題:怎樣知道一個(gè)對(duì)象的類型;
特點(diǎn): 內(nèi)部創(chuàng)建對(duì)象,并返回

function createPerson(name, age, job) {var o = new Object()o.name = nameo.age = ageo.job = jobo.sayName = function () { alert(this.name)}return o }

1.3 構(gòu)造函數(shù)模式

缺點(diǎn): 每個(gè)方法都要在每個(gè)實(shí)例上重新創(chuàng)建一遍!不同實(shí)例上的同名函數(shù)是不相等的,然而,創(chuàng)建2個(gè)完成同樣任務(wù)的Function實(shí)例的確沒有必要。
特點(diǎn)
沒有顯示創(chuàng)建對(duì)象;
沒有return;
將方法屬性賦值給this對(duì)象;
首字母大寫;
構(gòu)造函數(shù)創(chuàng)建的實(shí)例標(biāo)識(shí)為一種特定的類型

1.3.1 理解面試題

調(diào)用構(gòu)造函數(shù)創(chuàng)建對(duì)象,實(shí)際會(huì)經(jīng)歷以下4個(gè)步驟:

  • 創(chuàng)建一個(gè)新對(duì)象;
  • 將構(gòu)造函數(shù)的作用域賦值給新對(duì)象(this指向這個(gè)新對(duì)象)
  • 執(zhí)行構(gòu)造函數(shù)代碼(為這個(gè)新對(duì)象添加屬性方法)
  • 返回新對(duì)象
  • function Person(name, age, job) {this.name = namethis.age = agethis.job = jobthis.sayName = function () { // 每定義一個(gè)函數(shù),就是實(shí)例化一個(gè)對(duì)象alert(this.name)} } var p1 = new Person("Y",18,"police") var p2 = new Person("H",8,"teacher") // p1.constructor == Person // p2.constructor == Person// ( p1 instanceOf Object ) true // ( p1 instanceOf Person ) true // ( p2 instanceOf Object ) true // ( p2 instanceOf Person ) true
    • 在全局作用域調(diào)用函數(shù),this總是指向GLOBAL對(duì)象
    function person(name, age, job) {this.name = namethis.age = agethis.job = jobthis.sayName = function () { alert(this.name)} } person('Leo', 16, 'doctor') window.sayName() //leo

    1.3.2 將構(gòu)造函數(shù)當(dāng)做函數(shù)

    任何函數(shù),只要通過new操作符來調(diào)用,便可以作為構(gòu)造函數(shù);若不用,即與普通函數(shù)無異。this會(huì)指向Global對(duì)象(在瀏覽器中就是window)

    1.3.3 將方法定義到構(gòu)造函數(shù)外部

    缺點(diǎn): 在全局作用域上定義的函數(shù),若只能被某個(gè)對(duì)象調(diào)用,不合理;并且,如果對(duì)象需要定義很多方法,則需要定義很多個(gè)全局函數(shù),對(duì)于這個(gè)自定義的引用類型就絲毫沒有封裝性可言。

    function Person(name, age, job) {this.name = namethis.age = agethis.job = job } function sayName() {alert(this.name) }

    1.4 原型模式

    1.4.1 理解原型模式

    function Person() {} Person.prototype.name = "Y" Person.prototype.age = 18 Person.prototype.job = "police" Person.prototype.sayName = function () {alert(this.name) }
  • 使用原型對(duì)象的好處:讓所有的對(duì)象實(shí)例共享它所包含的屬性和方法;
  • 只要?jiǎng)?chuàng)建了一個(gè)新函數(shù),就會(huì)為該函數(shù)創(chuàng)建一個(gè)prototype屬性,指向函數(shù)的原型對(duì)象
  • 原型對(duì)象會(huì)自動(dòng)獲得constructor屬性,該屬性包含一個(gè)指向prototype屬性所在函數(shù)的指針(constructor屬性指向構(gòu)造函數(shù));
  • 對(duì)象的constructor屬性最初是用來表示對(duì)象類型的;
  • 構(gòu)造函數(shù)創(chuàng)建的實(shí)例,實(shí)例內(nèi)部包含一個(gè)指針,指向構(gòu)造函數(shù)的原型對(duì)象
  • Person.prototype.isPrototypeOf(p1) // true
  • Object.getPrototypeOf(p1) == Person.prototype // true
  • 代碼讀取某個(gè)對(duì)象某個(gè)屬性時(shí),先搜索對(duì)象實(shí)例,若無再搜索原型對(duì)象;
  • 若實(shí)例中添加的屬性和原型屬性同名,會(huì)屏蔽原型中的屬性(因?yàn)閷?shí)例只能訪問原型中的值,而不能重寫);
  • 若將實(shí)例中的同名屬性設(shè)為null,并不能恢復(fù)與原型的連接,需要使用delete操作符完全刪除實(shí)例屬性;
  • p1.hasOwnProperty("name")// true hasOwnProperty()方法可以檢測(cè)一個(gè)屬性是存在于實(shí)例中還是存在于原型,若來自實(shí)例則返回true
  • 1.4.2 in操作符

    in操作符會(huì)在通過對(duì)象能訪問給定屬性時(shí)返回true,無論屬性存在于實(shí)例還是原型中

    "name" in p1 // true

    1.4.3 確認(rèn)屬性存在于原型

    function hasPrototypeProperty(object,name) {return !object.hasOwnProperty(name) && (name in object) }

    1.4.4 更簡(jiǎn)單的原型語法

    缺點(diǎn): constructor屬性不再指向Person,切斷了實(shí)例和原型對(duì)象的聯(lián)系;對(duì)包含引用類型值的屬性,被實(shí)例共享會(huì)造成問題。
    特點(diǎn): 減少不必要的輸入(每添加一個(gè)屬性/方法就要多敲一遍Person.prototype)

    將Person.prototype設(shè)置為一個(gè)以對(duì)象字面量形式創(chuàng)建的新對(duì)象,本質(zhì)上重寫了prototype對(duì)象(創(chuàng)建函數(shù)時(shí)自動(dòng)創(chuàng)建的原型對(duì)象),導(dǎo)致constructor屬性指向Object構(gòu)造函數(shù),盡管instanceof還能返回正確的結(jié)果。

    function Person() {} Person.prototype = {name : "Y",age : 18,job : "police",sayName: function () {alert(this.name)} } p1 instanceof Object // true p1 instanceof Person // true p1.constructor == Person // false p1.constructor == Object // true

    增加constructor屬性,確保該屬性能訪問到適當(dāng)?shù)闹怠?/p> function Person() {} Person.prototype = {constructor : Person,name : "Y",age : 18,job : "police",sayName: function () {alert(this.name)} }

    1.4.5 原生對(duì)象的問題

    function Person() {} Person.prototype = {constructor : Person,friends:["Yoona","Jessica"], // 數(shù)組,引用類型name : "Y",age : 18,job : "police",sayName: function () {alert(this.name)} } p1.friends.push("Krystal") p1.friends == p2.friends

    1.4.6 組合使用構(gòu)造函數(shù)模式和原型模式

    構(gòu)造函數(shù)模式用于定義實(shí)例屬性,原型模式用于定義方法和共享的屬性。(實(shí)例屬性中的引用類型互不干擾)

    function Person(name, age, job) {this.name = namethis.age = agethis.job = jobthis.friends = ["Yoona","Jessica"] }Person.prototype = {constructor : Person,sayName: function () {alert(this.name)} }

    1.4.7 原生對(duì)象的原型

    通過原生對(duì)象的原型,不僅可以取得所有默認(rèn)方法的引用,也可以定義新方法。但不推薦在產(chǎn)品化的程序中修改原生對(duì)象的原型:
    如果因?yàn)槟硞€(gè)實(shí)現(xiàn)中缺少某個(gè)方法,就在原始對(duì)象的原型中添加,那么當(dāng)在另一個(gè)支持該方法的實(shí)現(xiàn)中運(yùn)行代碼時(shí),就可能會(huì)導(dǎo)致命名沖突,而且這樣做也可能會(huì)意外地重寫原生方法。

    1.5 梳理

    1.6 修改原生對(duì)象的原型

    String.prototype.startsWith = function(){}

    在當(dāng)前環(huán)境中,所有字符串都可以調(diào)用startsWith,但不推薦,可能會(huì)產(chǎn)生命名沖突,也可能會(huì)意外地重寫原生方法。

    String.prototype. toString = function () {console.log('修改原生對(duì)象默認(rèn)方法') }'str'.toString() // 修改原生對(duì)象默認(rèn)方法

    將原生對(duì)象原型指向空,沒效果

    String.prototype = null console.log('str'.toString()) // str

    2. 屬性類型 P139

    2.1 數(shù)據(jù)屬性

  • [[Configurable]]:能否通過delete刪除屬性,默認(rèn)為true
  • [[Enumerable]]:能否通過for-in循環(huán)返回屬性,默認(rèn)為true
  • [[Writeable]]:能否修改屬性的值,默認(rèn)為true
  • [[Value]]:屬性值,默認(rèn)為undefined
    • 一旦把屬性定義為不可配置的,就不能再把它變回可配置了;
    • 要修改屬性默認(rèn)的特性,必須使用Object.defineProperty(),3個(gè)參數(shù):對(duì)象、屬性名、描述符對(duì)象(屬性必須是數(shù)據(jù)屬性),若不指定數(shù)據(jù)屬性,則默認(rèn)為false;

    2.2 訪問器屬性

  • 包含一對(duì)getter和setter函數(shù)(都不是必須的),有4個(gè)特性:
    1) [[Configurable]]
    2) [[Enum而able]]
    3) [[Get]]:讀取屬性時(shí)默認(rèn)調(diào)用的函數(shù),默認(rèn)值undefined
    4) [[Set]]:寫入屬性時(shí)默認(rèn)調(diào)用的函數(shù),默認(rèn)值undefined
    • 屬性 _year 前面的下劃線用于表示只能通過對(duì)象方法訪問的屬性;
    • 使用訪問器屬性的常見方式:設(shè)置一個(gè)屬性的值會(huì)導(dǎo)致其他屬性發(fā)生變化;

    2.3 讀取屬性

    Object.getOwnPropertyDescriptor(),2個(gè)參數(shù):對(duì)象、屬性

    var descriptor = Object.getOwnPropertyDescriptor(person,"age") alert(age.value) alert(age.enumerable) alert(age.configurable) alert(age.get)

    方法集合

    Object.defineProperty() // 修改屬性默認(rèn)值 Object.getOwnPropertyDescriptor() //讀取屬性的描述符 誰誰的原型對(duì)象.isPrototypeOf(實(shí)例) // 參數(shù)是實(shí)例,判斷實(shí)例內(nèi)部是否有指向構(gòu)造函數(shù)原型對(duì)象的指針 hasOwnProperty() // 檢測(cè)屬性來自實(shí)例(返回true)還是原型

    3. 繼承(子類繼承父類的特征和行為)

    3.1 原型鏈

    原型鏈的問題

  • P166 原型鏈雖然很強(qiáng)大,可以用它來實(shí)現(xiàn)繼承,但它也存在一些問題,其中最主要的問題來自包含引用類型值的原型。包含引用類型值的原型屬性會(huì)被所有實(shí)例共享,因此要在構(gòu)造函數(shù),而不是原型對(duì)象中定義屬性。
  • 在創(chuàng)建子類型的實(shí)例時(shí),不能向超類型的構(gòu)造函數(shù)中傳遞參數(shù)。(沒有辦法在不影響所有對(duì)象實(shí)例的情況下,給超類型的構(gòu)造函數(shù)傳遞參數(shù))
  • 讓原型對(duì)象等于另一個(gè)類型的實(shí)例。

    SubType.prototype = new SuperType()

    SubType的實(shí)例指向SubType的原型,進(jìn)而又指向SuperType的原型

    3.2 默認(rèn)的原型

    所有引用類型默認(rèn)都繼承了Object,所有函數(shù)的默認(rèn)原型都是Object的實(shí)例,因此默認(rèn)原型都會(huì)包含一個(gè)內(nèi)部指針,指向Object.prototype,這也正是所有自定義類型都會(huì)繼承toString()、valueOf()等默認(rèn)方法的根本原因。完整的原型鏈如下:

    instance instanceof Object // true instance instanceof SuperType // true instance instanceof SubType // trueObject.prototype.isPrototypeOf(instance) // true SuperType.prototype.isPrototypeOf(instance) // true SubType.prototype.isPrototypeOf(instance) // true function Fun() {}console.log(Fun.prototype.__proto__==Object.prototype) // true

    3.3 組合繼承

  • 父構(gòu)造函數(shù)內(nèi)有引用類型屬性值
  • 子構(gòu)造函數(shù)內(nèi)使用call(保證了實(shí)例不會(huì)都指向同一個(gè)引用類型)
  • 子構(gòu)造函數(shù)原型指向父構(gòu)造函數(shù)原型(Object.create)
  • 子構(gòu)造函數(shù)原型里的構(gòu)造器指向自己(知曉實(shí)例由誰創(chuàng)建)
  • 4. 方法整理

    • A.isPrototypeOf(a)
      // 實(shí)例a的__proto__指向A的原型
      // 判斷原型對(duì)象A是否是實(shí)例a的原型,是則返回true
    • a.hasOwnProperty(‘name’) 判斷屬性是否存在于實(shí)例中(實(shí)例屬性),是則返回true
      Object.keys() 獲得對(duì)象上所有可枚舉的屬性
    • ‘name’ in a 無論原型/實(shí)例,只要是能訪問得到的屬性,in操作符返回true(包括constructor)'name’字符串
      for-in循環(huán),返回所有能通過對(duì)象訪問的、可枚舉的屬性 ,(遍歷一個(gè)實(shí)例對(duì)象,原型上的屬性也會(huì)打印、要只打印實(shí)例屬性,需要配合hasOwnProperty)
    • Object.getOwnPropertyNames(),得到所有實(shí)例屬性,包括constructor
    function Test(name) {this.name = name } Test.prototype.name = 'hhh' let tObj = new Test('yyy') console.log('name' in tObj) // true console.log('constructor' in tObj) // true for(var prop in tObj){console.log('for-in', prop) // name }

    總結(jié)

    以上是生活随笔為你收集整理的重学《JavaScript 高级程序设计》笔记 第6章对象的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。