likes
comments
collection
share

一道简单的构造函数题目,让我失眠了...

作者站长头像
站长
· 阅读数 14

一道简单的构造函数题目,让我失眠了...

上个礼拜,我的老师给我们布置了一道与构造函数、原型对象相关的代码题目。

一道简单的构造函数题目,让我失眠了...

抱着不想被老师点名回答时尴尬的“罚站”的心态😅,自认为已经学会了构造函数的原型关系,应该一下子就画出老师想要的。

结果,没想到我肝到半夜一点半!!!😮

一道简单的构造函数题目,让我失眠了...

经过我不断地调试、向老师解惑,让我来嗦嗦我一直困惑的问题吧~/(ㄒoㄒ)/~~

一、构造函数与原型对象、原型链的关系

js 面向对象由以下概念组成:

1. 构造函数有prototype 属性, 值是构造函数的对象, prototype对象归构造函数的所有实例共享。

2. 实例都拥有一个__proto__ 私有属性,对象在查找完自身的属性和方法后,会继续 沿着.__proto__ 指向的原型对象去查找。如果有,返回;如果没有,会继续沿着原型对象去查找。
    任何对象都有__proto__ ,不指定的话就指向Object。
    这些原型对象形成了一条链,叫做原型链。 
3. 构造函数的实例(cai实例)
    Pserson 构造函数
    Person.prototype 原型对象
    Person.prototype.__proto__ 原型对象 (Object)  js 内置的基于对象
    
    cai.toString() 原型链上的方法, 对象查找时会沿着原型链一直查找
    实例的方法 不要放到构造函数里声明,因为给每个实例分配一个函数,内存是吃不消的
    
    Object 是(函数也是)对象, 也是构造函数
    Object.prototype.__proto__ == null 到顶了,都没有, undefined  
    对象的终点是null 

    cai.__proto__->Person.prototype
                    Person.prototype.__proto__->Object.prototype
                        Object.prototype.__proto ->  null
            

一道简单的构造函数题目,让我失眠了...

实例的.__proto__属性指向原型对象,构造函数的prototype属性也指向原型对象。

一道简单的构造函数题目,让我失眠了...

如图的结果显示,构造函数的原型对象的.__proto__指向的原型对象是Object 而原型链的顶端是null

一道简单的构造函数题目,让我失眠了...

二、发现问题

老师给的代码如下:

function superType() {
    this.property = true
}
superType.prototype.getsuperValue = function () {
    return this.property;
}
function SubType() {
    this.subproperty = false
}
SubType.prototype = new superType()
SubType.prototype = {
    getsubValue() {
        return this.subproperty
    },
    someOtherMethod() {
        return false
    }
}
let instance = new SubType()
console.log(instance.getsuperValue())

打印的结果为什么是错误的❓

一道简单的构造函数题目,让我失眠了...

一开始,我也被上面的代码迷惑😟:SubType.prototype = new superType()SubType的原型对象不是superType实例嘛,instance为什么会找不到方法呢❓

let instance = new SubType()
console.log(instance.__proto__)
console.log(instance.__proto__.constructor)

一道简单的构造函数题目,让我失眠了...

我开始打印这个instance实例的原型对象和构造函数,结果发现:

  1. SubType.prototype被重写了?
  2. 那为什么它的构造函数是Object(){ }

三、解决问题根源

为了搞清楚上面几个问题,我写了以下代码进行详细讲解。

//所有的构造函数,都是基于object(){} 建立的
function superType() {
    this.property = true;
}

//superType原型对象上声明了一个函数
superType.prototype.getsuperValue = function () {
    return this.property;
};
console.log(superType.prototype.constructor)//结果:superType(){} 

function SubType() {
    this.subproperty = false;
}
console.log( SubType.prototype.constructor,"?????????")// SubType(){}

// SubType的prototype原型对象是superType实例,指向superType构造函数
SubType.prototype = new superType();
console.log( SubType.prototype.constructor)// superType(){}

//SubType的实例,找到SubType的prototype属性,是指向superType构造函数的实例,能够找到superType原型上的方法
let instance1 = new SubType(); // 会重写constructor属性
console.log(instance1.getsuperValue(),instance1.constructor);//结果:true, superType(){}


// 重写原型对象后,首先原型对象的constructor属性值(constructor的指向)会发生改变。
// SubType的prototype属性重写,原型对象上声明两个函数,构造函数是Object();
SubType.prototype = {
    getsubValue() {
        return this.subproperty;
    },
    someOtherMethod() {
        return false;
    }
}
console.log(SubType.prototype.constructor,"/////////");//结果:Object(){}
let instance2 = new SubType();//SubType的实例
console.log(instance2.getsubValue(),instance2.constructor)//结果:false,Object(){}

一道简单的构造函数题目,让我失眠了...

1. superType.prototype.getsuperValue = function () { }; 是在构造函数的prototype属性指向的原型对象上添加方法,这样并不是重写构造函数的原型对象,不会改变原构造函数原型对象的默认constructor属性,所以打印的superType.prototype.constructor的结果是superType(){}。

2.SubType.prototype = new SubType(),SubType的prototype原型对象是superType实例,在这个过程中,原来的constructor属性被重新指向了superType构造函数,所以打印的结果会是 superType(){}

3.SubType.prototype = { ... }是在重新给subType的原型对象写一个新的函数对象,而这个新的函数对象是基于Object建立的,所以此时的原型对象constructor不会指向subType,而是指向Object()

所以,在上面的解释下,我首先画出来一个关系图:

一道简单的构造函数题目,让我失眠了...

回到老师给我布置的课后作业中,我们看看问题在哪?

一道简单的构造函数题目,让我失眠了...

从图中我们可以看出,instance实例是在subType的原型对象重写之后,是没有办法找到superType的原型对象上的方法的,所以打印会出错。

一道简单的构造函数题目,让我失眠了...

如果使用的是如图这种方式,不重写subType的原型对象,就可以通过它的原型链访问getsuperValue()方法。

通过上面这个让我折磨到半夜的小作业,我突然明白了:在学习过程中还是要不断深入挖掘一下知识点之间的联系,也许我们自认为的学会了的知识,在一些时候突然就卡壳讲不出来为什么,那就说明我们学的并不扎实。😟

在这种关系中,我们要善用console.log()去进行打印出想要的结果,说不定在一遍遍的打印结果中,你又能发现更多奥秘😊!

喜欢这篇文章的话,就给作者留下一个小赞吧~❤