美文网首页
构造函数和原型对象

构造函数和原型对象

作者: milletmi | 来源:发表于2018-03-22 19:47 被阅读0次

    javascript使用构造函数和原型对象来进行面向对象编程

    构造函数

    在 JavaScript 中,构造器其实就是一个普通的函数。当使用 new 操作符 来作用这个函数时,它就可以被称为构造方法(构造函数)。

    • 以大写字母写构造函数(Capitalizing Constructors)

    • 构造函数是用new创建对象

    {
    function Person(){
        this.name ='millet'
    }
    let person1 =new Person();
    console.log(person1.name)//millet
    }
    
    • 根据需要,构造函数可以接受参数,如果没有参数,可以省略括号
    {
    function Person(){
        this.name ='millet'
    }
    let person1 =new Person;
    console.log(person1.name)//millet
    }
    
    • 如果忘记使用new操作符,则this将代表全局对象window
    {
    function Person(){
        this.name ='millet'
    }
    let person1 =Person;
    console.log(person1.name)//Uncaught TypeError: Cannot read property 'name' of undefined
    }
    
    
    • constructor,每个对象在创建时都自动拥有一个构造函数属性constructor,其中包含了一个指向其构造函数的引用。而这个constructor属性实际上继承自原型对象,而constructor也是原型对象唯一的自有属性
    {
    function Person(){
        this.name ='millet'
    }
    let person1 =new Person();
    console.log(person1)//
    **
    Person {
    name:"millet"
    __proto__:
    constructor:ƒ Person()
    arguments:null
    caller:null
    length:0
    name:"Person"
    prototype:{constructor: ƒ}
    __proto__:ƒ ()
    [[FunctionLocation]]:VM206:3
    [[Scopes]]:Scopes[1]
    __proto__:Object
    }
    **
    console.log(person1.constructor === Person)//true
    console.log(person1.__proto__.constructor === Person)//true
    }
    
    • 返回值:
      函数中的return语句用来返回函数调用后的返回值,而new构造函数的返回值有点特殊。
      如果构造函数使用return语句但没有指定返回值,或者返回一个原始值,那么这时将忽略返回值,同时使用这个新对象作为调用结果
    {
    function Person(){
        this.name ='millet'
        return;
    }
    let person1 =new Person;
    console.log(person1)//{name:"millet"}
    }
    
    • instanceof操作符可以用来鉴别对象的类型,针对丢失new的构造函数的解决办法是在构造函数内部使用instanceof判断是否使用new命令,如果发现没有使用,则直接使用return语句返回一个实例对象
    {
    function Person(){
        this.name ='millet'
    }
    let person1 =new Person;
    console.log(person1 instanceof Person)//true
    }
    ** 优化构造函数写法 **
    {
    function Person(){
       if(!(this instanceof Person)){
              return new Person()
        }
        this.name ='millet'
    }
    let person1 =Person;
    console.log(person1.name)//millet
    let person2 =new Person;
    console.log(person1.name)//millet
    
    }
    
    
    

    原型对象

    为了解决构造函数的属性和方法无法被对象实例所共享的问题,我们可以把需要共享的属性和方法放在原型(prototype)对象上。原型对象上的所有属性和方法,都会被对象实例所共享。对于构造函数来说,prototype是作为构造函数的属性;对于对象实例来说,prototype是对象实例的原型对象。所以prototype即是属性,又是对象。

    {
    function Person(){
        this.name ='millet'
    }
    let person1 =Person;
    原型对象和实例对象的关系:
    console.log(person.prototype=== Person1.__proto__ )//true
    原型对象和构造函数的关系 :
    console.log(Person.prototype.constructor === Person)//true
    而实例对象和构造函数则没有直接关系,间接关系是实例对象可以继承原型对象的constructor属性:
    console.log(person1.constructor === Person)//true
    }
    
    

    constructor属性是原型对象上的一个属性,可以被所有实例对象所共享。要注意的是,prototype是构造函数的属性,而constructor则是构造函数的prototype属性所指向的那个对象,也就是原型对象的属性。由于constructor属性是一种原型对象和构造函数的关系,所以在修改原型对象的时候,一定要注意constructor的指向问题

    构造函数和原型组合模式

    {
    function Person(){
        this.name ='millet'
    }
    Person.prototype ={
    constructor:Person,//重点,不写这一句的话console.log(person1.constructor === Person);//false
    say: function(){
    cosole.log(this.name )
    }
    }
    let person1 =new Person;
    console.log(person1.name)//millet
    }
    

    原型链的特点有

    a:读取对象的某个属性时,JavaScript引擎先寻找对象本身的属性,如果找不到,就到它的原型去找,如果还是找不到,就到原型的原型去找。如果直到最顶层的Object.prototype还是找不到,则返回undefined。

    b:如果对象自身和它的原型,都定义了一个同名属性,那么优先读取对象自身的属性,这叫做“覆盖”(overiding)。

    c:一级级向上在原型链寻找某个属性,对性能是有影响的。所寻找的属性在越上层的原型对象,对性能的影响越大。如果寻找某个不存在的属性,将会遍历整个原型链。

    相关文章

      网友评论

          本文标题:构造函数和原型对象

          本文链接:https://www.haomeiwen.com/subject/xfqzqftx.html