1. 程式人生 > 程式設計 >JavaScript原型Prototype詳情

JavaScript原型Prototype詳情

目錄
  • 1、概述
    • 1.1原型是什麼
    • 1.2獲取原型
  • 2、原型屬性
    • 2.1利用原型新增屬性與方法。
    • 2.2訪問原型屬性原型方法
  • 3、自有屬性與原型屬性
    • 3.1檢測自有屬性或者原型屬性
  • 4、isPrototypeOf()方法
    • 5、擴充套件內建物件
      • 6、結語

        1、概述

        1.1原型是什麼

        中,函式是一個包含屬性和方法的Function型別的物件。而原型(Prototype )就是Function型別物件的一個屬性。

        在函式定義是包含了prototype屬性,它的初始值是一個空物件 。在Script中並沒有定義函式的原始型別,所以原型可以是任何型別。

        原型是用於儲存物件的共享屬性和方法的,原型的屬性和方法並不會影響函式本身的屬性和方法。

        示例程式碼驗證如下:

        function fun() {
          console.log('函式原型')
        }
        console.log(fun.prototype) // {}
        
        

        fun.prototype返回的也是一個空物件,但是這不說明Object.prototype中沒有屬性或者方法,這些屬性和方法為不可列舉的,示例程式碼如下所示:

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

        其中,constructor屬性指向該建構函式的引用,程式碼如下:

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

        1.2獲取原型

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

        通過建構函式的prototype屬性。

        通過Object.getPrototypeOf(obj)方法。

        這兩個的區別就是建構函式的prototype屬性一般只配合建構函式使用,而Object.getPrototypeOf(obj)方法一般是獲取建構函式例項化後的物件的原型方法。

        例項程式碼如下:

        // 建構函式
        function Person(name) {
          this.name = name
        }
        
        // 指向建構函式http://www.cppcns.com的原型
        var p1 = Person.prototype
        
        var person = new Person('一碗周')
        
        // 指向建構函式的原型
        var p2 = Object.getPrototypeOf(person)
        
        console.log(p1 === p2) // true
        
        

        獲取原型後可以跟操作物件似的進行操作,因為原型本身就是一個物件。

        2、原型屬性

        JavaScript中,函式本身也是一個包含了方法和屬性的物件。接下將學習函式物件的另一個屬性——prototype,這個屬性的初始值是一個空物件。

        2.1利用原型新增屬性與方法。

        為物件新增屬性和方法的另一種用法就是通過原型為其新增。當為一個建構函式新增原型屬性和原型方法時,通過該建構函式new出的所有物件共享該屬性和方法。

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

        新增屬性和方法的方式具有如下幾種方式

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

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

        直接新增物件到原型。

        示例程式碼如下所示:

        //建構函式
        function Fun() {}
        //直接為建構函式新增屬性和方法
        Fun.prototype.str = '這是一個字串'
        Fun.prototype.fn = function () {
          console.log('這是一個方法')
        }
        //通過 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()
        //直接為其定義個物件覆蓋到之前的原型上
        Fun.prototype = {
          name: '一碗周',fun: function () {
            console.log('this is function')
          },}
        Fun.prototype.fun()
        var fun = new Fun()
        fun.fun()
        
        

        2.2訪問原型屬性原型方法

        對於原型來說,最重要的一點就是它的實時性 。由於在JavaScript中,幾乎所有的物件都是通過傳引用的方式來傳遞的,因此我們所建立的的每個新物件實體中並沒有一份屬於自己的原型副本。這就意味著我們隨時修改prototype屬性,並且由同一構造器建立的所有物件的prototype屬性也都會同時改變,包括我們之間通過構造器建立的屬性和方法。

        還是上面那段程式碼我們向原型中新增一個新方法,並呼叫,示例程式碼如下所示:

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

        我們之前建立的物件可以訪問新加的原型屬性和原型方法。

        3、自有屬性與原型屬性

        我們先來建立一個建構函式,併為其新增兩個原型屬性。

        //建構函式
        function Fun() {}
        //新增原型屬性和方法
        Fun.prototype.name = '一碗粥'
        Fun.prototype.print = function () {
          console.log('this is function')
        }
        
        

        在通過該建構函式建立一個物件,為其設定屬性和方法

        //通過建構函式建立物件
        var fun = new Fun()
        //為物件新增屬性和方法
        fun.name = '一碗周'
        fun.SayMe = function () {
          console.log('this is SayMe')
        }
        
        

        現在我們的fun物件,擁有自有屬性/方法兩個,原型屬性/方法兩個。我們依次來訪問這些屬性和方法。

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

        當我們訪問name屬性時,JavaScript引擎會遍歷fun這個物件的所有屬性,並返回name屬性的值。SayMe()方法也是樣的道理。但是到print()方法時,JavaScript引擎還是會遍歷這個物件所有屬性,這時就找不到一個叫print()方法了,接下來JavaScript引擎就會訪問建立當前物件的構造器函式的原型,也就是我們的Fun.prototype,如果其中有該屬性,則立即返回,否則返回undefined或者丟擲異常

        結論:當有自有屬性時,優先訪問自有屬性,訪問完自有屬性再去訪問原型屬性 。

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

        現在已經知道自有屬性和原型屬性的概念以及用途了,但是我們怎麼知道一個屬性時自由屬性還是原有屬性,JavaScript中提供以下兩種方式來檢測一個屬性的情況

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

        來使用in關鍵字來檢測物件以及原型鏈中是否具有指定屬性。

        測試程式碼如下:

        // 通過Object.prototype.hasOwnProperty(prop)方法檢測是否為自有屬性
        console.log(fun.hasOwnProperty('name')) // true
        console.log(fun.hasOwnProperty('print')) // false
        // 如果一個不存在的屬性檢測結果也是為false
        console.log(fun.hasOwnProperty('SayMe')) // true
        
        // 通過 in 運算子
        www.cppcns.comconsole.log('name' in fun) // true
        console.log('print' in fun) // true
        console.log('SayMe' in fun) // true
        
        

        通過測試我們發現,這兩個方法並不能檢測一個屬性是不是一個自有屬性或者原型屬性,但是將這兩個方法結合起來就可以檢測是自有屬性還是原型屬性了,

        示例代hZQEHV碼如下:

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

        測試如下:

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

        4、isPrototypeOf()方法

        isPrototypeOf()方法用來檢測一個物件是否存在於另一個物件的原型鏈中,如果存在就返回true,否則就返回false。

        例項程式碼如下所示:

        // 定義一個物件,用於賦值給原型物件
        var obj = function () {
          this.name = '一碗周'
        }
        var Hero = function () {} // 定義建構函式
        // 將定義的物件賦值給建構函式的原型
        Hero.prototype = obj
        
        // 通過Hero建立物件
        var hero1 = new Hero()
        var hero2 = new Hero()
        // 判斷建立的兩個物件是否在 obj 的原型鏈中
        console.log(obj.isPrototypeOf(hero1)) // true
        console.log(obj.isPrototypeOf(hero2)) // true
        
        

        5、擴充套件內建物件

        JavaScript中的內建物件有些也具prototype屬性,利用內建物件的prototype屬性可以為內建物件擴充套件屬性和方法。

        通過原型擴充套件內建物件的屬性和方法非常靈活,根據個性化要求制定JavaScript語言的具體內容。

        擴充套件內建物件的方式有兩種,具體如下所示:

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

        通過Object物件的defineProperty()方法為其新增屬性或者方法。這種方式會比第一種方式要好,是建立的屬性和方法更具有安全性

        示例程式碼如下所示:

        // 為 Object 擴充套件屬性和方法
        // 使用第一種方式
        Object.prototype.MyPrint = function () {
          console.log('this is MyPrint()')
        }
        // 使用第二種方式
        Object.defineProperty(Object.prototype,'MyInput',{
          value: function () {
            console.log('this is MyInput()')
          },})
        // 呼叫
        Object.prototype.MyPrint() // this is MyPrint()
        Object.prototype.MyInput() // this is MyInput()
        
        

        6、結語

        這篇文章介紹了JavaScript中的原型的概念、原型屬性、如何檢測自有屬性和原型屬性以及如何擴充套件內建物件

        到此這篇關於JavaScript原型Prototype詳情的文章就介紹到這了,更多相關JavaScript原型內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!