溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

JavaScript原型Prototype怎么使用

發(fā)布時(shí)間:2021-12-01 15:07:32 來源:億速云 閱讀:194 作者:iii 欄目:開發(fā)技術(shù)

這篇文章主要講解了“JavaScript原型Prototype怎么使用”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“JavaScript原型Prototype怎么使用”吧!

    1、概述

    1.1原型是什么

    JavaScript中,函數(shù)是一個(gè)包含屬性和方法的Function類型的對象。而原型(Prototype )就是Function類型對象的一個(gè)屬性。

    在函數(shù)定義是包含了prototype屬性,它的初始值是一個(gè)空對象 。在JavaScript中并沒有定義函數(shù)的原始類型,所以原型可以是任何類型。

    原型是用于保存對象的共享屬性和方法的,原型的屬性和方法并不會(huì)影響函數(shù)本身的屬性和方法。

    示例代碼驗(yàn)證如下:

    function fun() {
      console.log('函數(shù)原型')
    }
    console.log(fun.prototype) // {}

    fun.prototype返回的也是一個(gè)空對象,但是這不說明Object.prototype中沒有屬性或者方法,這些屬性和方法為不可枚舉的,示例代碼如下所示:

    function fun() {
      console.log('函數(shù)原型')
    }
    
    console.log(fun.prototype) // {}
    // 通過 Object.getOwnPropertyNames() 獲取全部屬性
    console.log(Object.getOwnPropertyNames(fun.prototype)) // [ 'constructor' ]

    其中,constructor屬性指向該構(gòu)造函數(shù)的引用,代碼如下:

    // constructor屬性
    
    console.log(fun.prototype.constructor) // [Function: fun]
    
    console.log(fun.prototype.constructor === fun) // true

    1.2獲取原型

    了解了原型的概念以及作用之后,我們需要獲取到原型才能對其進(jìn)行操作,在JavaScript中獲取原型的方式有兩種,如下所示:

    通過構(gòu)造函數(shù)的prototype屬性。

    通過Object.getPrototypeOf(obj)方法。

    這兩個(gè)的區(qū)別就是構(gòu)造函數(shù)的prototype屬性一般只配合構(gòu)造函數(shù)使用,而Object.getPrototypeOf(obj)方法一般是獲取構(gòu)造函數(shù)實(shí)例化后的對象的原型方法。

    實(shí)例代碼如下:

    // 構(gòu)造函數(shù)
    function Person(name) {
      this.name = name
    }
    
    // 指向構(gòu)造函數(shù)的原型
    var p1 = Person.prototype
    
    var person = new Person('一碗周')
    
    // 指向構(gòu)造函數(shù)的原型
    var p2 = Object.getPrototypeOf(person)
    
    console.log(p1 === p2) // true

    獲取原型后可以跟操作對象似的進(jìn)行操作,因?yàn)樵捅旧砭褪且粋€(gè)對象。

    2、原型屬性

    JavaScript中,函數(shù)本身也是一個(gè)包含了方法和屬性的對象。接下將學(xué)習(xí)函數(shù)對象的另一個(gè)屬性——prototype,這個(gè)屬性的初始值是一個(gè)空對象。

    2.1利用原型添加屬性與方法。

    為對象添加屬性和方法的另一種用法就是通過原型為其添加。當(dāng)為一個(gè)構(gòu)造函數(shù)添加原型屬性和原型方法時(shí),通過該構(gòu)造函數(shù)new出的所有對象共享該屬性和方法。

    PS:所謂的原型屬性或者原型方法就是通過原型添加的屬性或者方法。

    添加屬性和方法的方式具有如下幾種方式

    直接為其增加屬性或者方法

    通過Object.defineProperty()方法,添加屬性或者方法。這種方式比第一種方式更具有安全性。

    直接添加對象到原型。

    示例代碼如下所示:

    //構(gòu)造函數(shù)
    function Fun() {}
    //直接為構(gòu)造函數(shù)添加屬性和方法
    Fun.prototype.str = '這是一個(gè)字符串'
    Fun.prototype.fn = function () {
      console.log('這是一個(gè)方法')
    }
    //通過 defineProperty 添加屬性或者方法
    Object.defineProperty(Fun.prototype, 'MyFun', {
      value: function () {
        console.log('this is MyFun')
      },
    })
    //測試
    console.log(Fun.prototype.str)
    Fun.prototype.fn()
    Fun.prototype.MyFun()
    var fun = new Fun()
    fun.MyFun()
    //直接為其定義個(gè)對象覆蓋到之前的原型上
    Fun.prototype = {
      name: '一碗周',
      fun: function () {
        console.log('this is function')
      },
    }
    Fun.prototype.fun()
    var fun = new Fun()
    fun.fun()

    2.2訪問原型屬性原型方法

    對于原型來說,最重要的一點(diǎn)就是它的實(shí)時(shí)性 。由于在JavaScript中,幾乎所有的對象都是通過傳引用的方式來傳遞的,因此我們所創(chuàng)建的的每個(gè)新對象實(shí)體中并沒有一份屬于自己的原型副本。這就意味著我們隨時(shí)修改prototype屬性,并且由同一構(gòu)造器創(chuàng)建的所有對象的prototype屬性也都會(huì)同時(shí)改變,包括我們之間通過構(gòu)造器創(chuàng)建的屬性和方法。

    還是上面那段代碼我們向原型中添加一個(gè)新方法,并調(diào)用,示例代碼如下所示:

    Fun.prototype.fn = function () {
      console.log('這是一個(gè)方法')
    }
    fun.fn() //這是一個(gè)方法

    我們之前創(chuàng)建的對象可以訪問新加的原型屬性和原型方法。

    3、自有屬性與原型屬性

    我們先來創(chuàng)建一個(gè)構(gòu)造函數(shù),并為其添加兩個(gè)原型屬性。

    //構(gòu)造函數(shù)
    function Fun() {}
    //添加原型屬性和方法
    Fun.prototype.name = '一碗粥'
    Fun.prototype.print = function () {
      console.log('this is function')
    }

    在通過該構(gòu)造函數(shù)創(chuàng)建一個(gè)對象,為其設(shè)置屬性和方法

    //通過構(gòu)造函數(shù)創(chuàng)建對象
    var fun = new Fun()
    //為對象添加屬性和方法
    fun.name = '一碗周'
    fun.SayMe = function () {
      console.log('this is SayMe')
    }

    現(xiàn)在我們的fun對象,擁有自有屬性/方法兩個(gè),原型屬性/方法兩個(gè)。我們依次來訪問這些屬性和方法。

    //訪問屬性和方法
    console.log(fun.name) // 一碗周
    fun.SayMe() // this is SayMe
    fun.print() // this is function

    當(dāng)我們訪問name屬性時(shí),JavaScript引擎會(huì)遍歷fun這個(gè)對象的所有屬性,并返回name屬性的值。SayMe()方法也是樣的道理。但是到print()方法時(shí),JavaScript引擎還是會(huì)遍歷這個(gè)對象所有屬性,這時(shí)就找不到一個(gè)叫print()方法了,接下來JavaScript引擎就會(huì)訪問創(chuàng)建當(dāng)前對象的構(gòu)造器函數(shù)的原型,也就是我們的Fun.prototype,如果其中有該屬性,則立即返回,否則返回undefined或者拋出異常

    結(jié)論:當(dāng)有自有屬性時(shí),優(yōu)先訪問自有屬性,訪問完自有屬性再去訪問原型屬性 。

    3.1檢測自有屬性或者原型屬性

    現(xiàn)在已經(jīng)知道自有屬性和原型屬性的概念以及用途了,但是我們怎么知道一個(gè)屬性時(shí)自由屬性還是原有屬性,JavaScript中提供以下兩種方式來檢測一個(gè)屬性的情況

    使用Object.prototype.hasOwnProperty(prop)方法來檢測prop屬性是否是自由屬性,該方法返回一個(gè)布爾值,如果是自有屬性則返回true,否則返回false。

    來使用in關(guān)鍵字來檢測對象以及原型鏈中是否具有指定屬性。

    測試代碼如下:

    // 通過Object.prototype.hasOwnProperty(prop)方法檢測是否為自有屬性
    console.log(fun.hasOwnProperty('name')) // true
    console.log(fun.hasOwnProperty('print')) // false
    // 如果一個(gè)不存在的屬性檢測結(jié)果也是為false
    console.log(fun.hasOwnProperty('SayMe')) // true
    
    // 通過 in 運(yùn)算符
    console.log('name' in fun) // true
    console.log('print' in fun) // true
    console.log('SayMe' in fun) // true

    通過測試我們發(fā)現(xiàn),這兩個(gè)方法并不能檢測一個(gè)屬性是不是一個(gè)自有屬性或者原型屬性,但是將這兩個(gè)方法結(jié)合起來就可以檢測是自有屬性還是原型屬性了,

    示例代碼如下:

    function DetectionAttributes(obj, attr) {
      if (attr in obj) {
        if (obj.hasOwnProperty(attr)) {
          // 如果是自有屬性屬性返回1
          return 1
        } else {
          // 如果是原型屬性返回0
          return 0
        }
      } else {
        // 沒有這個(gè)屬性返回 -1
        return -1
      }
    }

    測試如下:

    console.log(DetectionAttributes(fun, 'name')) // 1
    console.log(DetectionAttributes(fun, 'print')) // 0
    console.log(DetectionAttributes(fun, 'SayMe')) // 1

    4、isPrototypeOf()方法

    isPrototypeOf()方法用來檢測一個(gè)對象是否存在于另一個(gè)對象的原型鏈中,如果存在就返回true,否則就返回false。

    實(shí)例代碼如下所示:

    // 定義一個(gè)對象,用于賦值給原型對象
    var obj = function () {
      this.name = '一碗周'
    }
    var Hero = function () {} // 定義構(gòu)造函數(shù)
    // 將定義的對象賦值給構(gòu)造函數(shù)的原型
    Hero.prototype = obj
    
    // 通過Hero創(chuàng)建對象
    var hero1 = new Hero()
    var hero2 = new Hero()
    // 判斷創(chuàng)建的兩個(gè)對象是否在 obj 的原型鏈中
    console.log(obj.isPrototypeOf(hero1)) // true
    console.log(obj.isPrototypeOf(hero2)) // true

    5、擴(kuò)展內(nèi)置對象

    JavaScript中的內(nèi)置對象有些也具prototype屬性,利用內(nèi)置對象的prototype屬性可以為內(nèi)置對象擴(kuò)展屬性和方法。

    通過原型擴(kuò)展內(nèi)置對象的屬性和方法非常靈活,根據(jù)個(gè)性化要求制定JavaScript語言的具體內(nèi)容。

    擴(kuò)展內(nèi)置對象的方式有兩種,具體如下所示:

    通過直接新增屬性和方法。

    通過Object對象的defineProperty()方法為其新增屬性或者方法。這種方式會(huì)比第一種方式要好,是創(chuàng)建的屬性和方法更具有安全性

    示例代碼如下所示:

    // 為 Object 擴(kuò)展屬性和方法
    // 使用第一種方式
    Object.prototype.MyPrint = function () {
      console.log('this is MyPrint()')
    }
    // 使用第二種方式
    Object.defineProperty(Object.prototype, 'MyInput', {
      value: function () {
        console.log('this is MyInput()')
      },
    })
    // 調(diào)用
    Object.prototype.MyPrint() // this is MyPrint()
    Object.prototype.MyInput() // this is MyInput()

    感謝各位的閱讀,以上就是“JavaScript原型Prototype怎么使用”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對JavaScript原型Prototype怎么使用這一問題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是億速云,小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!

    向AI問一下細(xì)節(jié)

    免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

    AI