ES5面向对象中容易混淆的点

36 阅读2分钟

概要:关于Object、构造函数、实例对象、原型对象、构造函数的prototype属性、prototype对象上的constructor属性、Object.create({})的理解

要点提炼
  • Object 可以理解为是一个构造函数
  • new Object()则是Object的一个实例对象,平时我们字面量的写法var obj = {}也属于实例对象
  • 构造函数的prototype属性的值是一个对象,这个对象就是构造函数生成的实例对象原型
//需要注意的是:实例对象是没有prototype属性
var obj = new Object();
obj.prototype //undefined 因为obj是实例对象
Object.prototype //这个则是obj的原型对象,因为Object相当于一个构造函数
  • prototype对象有一个constructor属性,默认指向prototype对象所在的构造函数
Object.prototype.constructor === Object  //true
var ConStrFun = function(){}
ConStrFun.prototype.constructor === ConStrFun  //true
  • 实例对象继承了原型对象的属性和方法
  • 原型对象其实也是一个实例对象,没有prototype属性的(prototype属性只有构造函数才有)
  • Object.create从实例对象生成另一个实例对象
var insObj = {a: 1, b: 2}; //定义一个实例对象
var newInsObj = Object.create(insObj); //通过insObj实例对象生成newInsObj实例对象
newInsObj.__proto__ === insObj; //true  insObj实例对象是newinsObj实例对象的原型对象
//这里需要注意的点是
//虽然insObj是newInsObj的原型对象,但不能使用instanceof来验证
newInsObj instanceof insObj //会报错
//如下解释:

instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。 单看上面提炼的要点,还是不方便理解,通过下面的示例及注释帮助进一步理解

var insObj = new ConStr();
insObj instanceof ConStr // true
//左边是实例对象,右边是构造函数;由此可看出 instanceof 是验证insObj实例对象的构造函数是否是ConStr
//也就是说右边需要是构造函数,不能是实例对象
示例及相关注释
//创建ConStr构造函数
var ConStr = function(x, y) {
    //判断 this 是否是 ConStr的实例,这里是为了避免实例化ConStr时忘记使用new的情况
    if(!(this instanceof ConStr)){
        return new ConStr(x, y);
    }
    this.x = x;
    this.y = y;
}
//在构造函数的prototype属性上添加getArea方法
//ConStr.prototype 则为 ConStr构造函数生成的实例对象 的 原型对象
//ConStr生成的实例对象 可以共享 原型对象 上的getArea方法
ConStr.prototype.getArea = function(){
    return this.x * this.y;
}
//insObj1和insObj2为 ConStr构造函数生成的实例对象
var insObj1 = new ConStr(1, 2);
var insObj2 = new ConStr(2, 4);
insObj1.getArea(); //2
insObj2.getArea(); //8