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()显示指定。
相关文章
相关标签/搜索