js面向對象精要-構造函數和原型對象

構造函數和原型對象

構造函數

  • 全部用同一個構造函數建立的對象都有相同的屬性和方法,若是想建立多個相同的對象,就能夠建立構造函數。
  • 構造函數和普通函數同樣,定義方式就是函數名字首字母大寫
function Person(){
        
    }
複製代碼
  • 定義好構造函數後,就能夠建立對象了。
var person1 = new Person()
    var person2 = new Person() 
複製代碼
  • 即便構造函數Person沒有顯示的返回任何東西,person1和person2會被認爲是一個新的Person類型的實例。new操做符會自動建立給定類型的對象並返回他們。這意味着能夠用instanceof 獲取對象的類型.
console.log(person1 instanceof Person) //true
    console.log(person2 instanceof Person) //true
複製代碼
  • 每一個對象在建立的時候,都會有個構造函數屬性(constructor),指向構造函數
console.log(person1.constructor === Person) //true
    console.log(person2.constructor === Person) //true
複製代碼
  • 爲構造函數建立屬性和方法。
function Person(name){
        this.name = name;
        this.sayName = function(){
            console.log(this.name)
        }
    }

    var person1 = new Person('aaa')
    var person2 = new Person('bbb')

    console.log(person1.name)   //aaa
    console.log(person2.name)   //bbb

    person1.sayName()   //aaa
    person2.sayName()   //bbb
複製代碼
  • 這樣的對象,每一個對象都擁有相同的屬性和方法,可是每一個對象都會被new,形成重複的損失,能夠用原型對象來避免,被屢次new.

原型對象

  • 幾乎全部的函數(除了一些內建函數)都有一個名爲prototype的屬性,該屬性是一個原型對象用來建立新的對象實例,全部建立的對象實例共享該原型對象。且這些對象實例能夠訪問原型對象的屬性。例如:hasOwnPrototype()方法被定義在Object的原型對象中,能夠被任何對象看成本身的屬性訪問。
var book = {
        title:'111'
    }

    console.log(title in book)  //true
    console.log(book.hasOwnPrototype('title'))  //true
複製代碼
  • 雖然book中沒有定義hasOwnPrototype(),可是可使用,由於該方法存在Object.prototype中。數組

  • 鑑別一個屬性是不是原型屬性函數

function hasPro(object,name){
        return name in object && object.hasOwnPrototype(name)
    }
    //true 表明是原型屬性
    //false 表明不是原型屬性
複製代碼
  • Person.prototype就是原型對象
  • 寫在原型對象的屬性和方法會被多個對象實例共用
  • isPrototypeOf()檢查一個對象是不是另外一個對象的原型對象
var object = {}
    console.log(Object.prototype.isPrototypeOf(object)) //true
複製代碼
  • 當讀取一個對象的屬性時,會先在自身查找有沒有該屬性,沒有的話,會在原型對象中查找,也沒有的話,會返回undefined
  • delete只能刪除對象的自有屬性,刪除不了原型對象的屬性

在構造函數中使用原型對象

function Person(name){
        this.name = name;
    }
    Person.prototype.sayName = function(){
        console.log(this.name)
    }

    var p1 = new Person('aaa')
    var p2 = new Person('bbb')

    console.log(p1.name)    //aaa
    console.log(p2.name)    //bbb

    p1.sayName()    //aaa
    p2.sayName()    //bbb
複製代碼
  • 上面把sayName()方法放在了Person的原型對象裏面,因此用new建立出來的對象實例能夠共用。p1和p2對象均可以使用sayName()方法。this值分別被賦值在p1和p2中。ui

  • 若是在原型對象上添加引用類型的值時,會形成多個對象同時改變。this

function Person(name){
        this.name = name;
    }

    Person.prototype.sayName = function (){
        console.log(this.name)
    }
    
    Person.prototype.favorite = [] //數組,引用類型

    var p1 = new Person('aaa')
    var p2 = new Person('bbb')

    p1.favorite.push('ccc')
    p2.favorite.push('ddd')

    console.log(p1.favorite)    //['ccc','ddd']
     console.log(p2.favorite)    //['ccc','ddd']

    // 由於在原型對象上添加了引用類型,致使p1和p2對象都添加了ccc和ddd
複製代碼
  • 使用對象字面形式代替原型對象
function Person(name){
        this.name = name
    }

    Person.prototype = {
        sayName:function(){
            console.log(this.name)
        },
        toString:function(){
            return this.name
        }
    }
複製代碼
  • 使用對象字面形式的缺點是對象實例的constructor指向了Object,而不是構造函數
var p1 = new Person('aaa')

    console.log(p1 instanceof Person)   //true
    console.log(p1.constructor === Person)  //false
    console.log(p1.constructor === Object)  //true

    // 能夠看出來對象實例p1的constructor指向了Objcet
複製代碼
  • 解決辦法:手動重置constructor屬性
function Person(name){
        this.name = name
    }

    Person.prototype = {
        constructor:Person,
        sayName:function(){
            console.log(this.name)
        }
    }

    var p1 = new Person('aaa')

    console.log(p1 instanceof Person)   //true
    console.log(p1.constructor === Person)  //true
    console.log(p1.constructor === Object)  //false
複製代碼
  • constructor是原型對象的屬性
  • 對象實例p1能夠調用constructor屬性
  • 對象實例p1的constructor指向構造函數或者Object,而且能夠手動改變對象實例的constructor,也就是原型對象的屬性constructor
  • p1.constructor = Person.prototype.constructor

內建對象也有原型對象

  • 好比數組
Array.prototype.sum = function(){
        return this.reduce((pre,cur)=>{
            return pre + cur
        })
    }

    var num = [1,2,3]
    var res = num.sum()

    console.log(6)
複製代碼
  • 一般,共享的方法和原始值的屬性被定義在原型對象裏面,其餘屬性被定義在構造函數裏

原型對象鏈和Object.prototype

原型對象鏈

  • 對象繼承原型對象。原型對象繼承它的原型對象,依次類推。
  • 全部對象自動繼承Object,確切的是,全部對象繼承Object.prototype

繼承自Object.prototype的方法

  • hasOwnPrototype():檢查是否存在一個給定名字的自有屬性
  • isPrototypeOf():檢查一個對象是不是另外一個對象的原型對象
  • valueOf():返回一個對象的值表達式
  • toString():返回一個對象的字符串表達式

對象繼承

  • 對象繼承是最簡單的繼承類型。只須要作的是指定哪一個對象是新對象。對象字面形式會隱士指定Object.prototype爲其[[Prototype]],也可用Object.create()顯示指定。
相關文章
相關標籤/搜索