首頁  >  問答  >  主體

javascript - JS面向对象的new操作

创建了一个函数Shape,在他的prototype上写了一个name属性和toString方法,接着输出Shape的name属性和调用toString方法。

然后new一个Shape的实例——Triangle,分别输出Triangle的name属性和调用toString方法,结果如下:

    var Shape = function () {};
    Shape.prototype.name = 'Shape';
    Shape.prototype.toString = function () {
        return this.name;
    }

    console.log(Shape.name); // ''
    console.log(Shape.toString()); // function () {}

    var Triangle = new Shape();
    console.log(Triangle.name); // 'Shape'
    console.log(Triangle.toString()); // 'Shape'

记得new操作完成了两件事:
1. 将this指向实例
2. 将实例的__proto__或者说[[prototype]]指向构造函数的prototype属性。(有不对和漏的地方请补充!)这样可以理解实例函数去__proto__中查找name属性和toString()方法。

而构造函数似乎直接去爬原型链了,为什么它不先在自身的属性中查找呢?试着给Triangle的prototype加一个同名属性和方法:

    Triangle.prototype = {}; // 这里还有一个疑问,new出来的对象
                             // 没有prototype属性,是因为函数要作为构造函数
                             // 所以内置了prototype属性么?

    Triangle.prototype.name = 'Triangle';
    Triangle.prototype.toString = function () {
        return 'I am ' + this.name;
    }

    console.log(Triangle.name); // 'Shape'
    console.log(Triangle.toString()); // 'Shape'

嘛...和构造函数一个德行,求解惑~ 谢谢!

PHP中文网PHP中文网2749 天前352

全部回覆(3)我來回復

  • 伊谢尔伦

    伊谢尔伦2017-04-10 14:32:40

    你想要的是这个吗?

    Triangle.name = 'Triangle';
    Triangle.toString = function() {
      return 'I am ' + this.name;
    }
    console.log(Triangle.name); // 'Triangle'
    console.log(Triangle.toString()); //  'I am Triangle' 
    

    只有函数对象的prototype属性才有特殊意义(可以被实例访问)
    Triangle只是个一般的、普通的对象,
    它的Triangle.prototype就和随便某个属性(如Triangle.abc)是一个级别的

    回覆
    0
  • PHP中文网

    PHP中文网2017-04-10 14:32:40

    看来题主还不是很理解js是基于原型的编程语言,它可以模仿面向对象,但它从根本上是基于原型的。

    如果题主想要模仿继承应该这么做:

    var Shape = function () {};
    Shape.prototype = {
      constructor: Shape,
      type: 'Shape',
      toString: function () {
        return this.type;
      }
    }
    
    var Triangle = function () {};
    Triangle.prototype = new Shape();
    Triangle.prototype.type = 'Triangle';
    

    可以试一下结果:

    var t = new Triangle();
    t instanceof Triangle // true
    t instanceof Shape // true
    t.toString() //'Triangle'
    

    接下来解释一下为什么题主你那样写不正确:
    1. var Triangle = new Shape(); 这句创建了一个Shape实例,而并没有创建一个新的原型。
    2. Triangle.prototype = {}; 这句以及接下来的几句都重新创建了一个原型,而并没有修改原本的原型。
    有什么疑问可以追问。

    回覆
    0
  • 怪我咯

    怪我咯2017-04-10 14:32:40

    var Shape = function () {};
    因为构造函数本身就没有带有这个属性或者方法,所以新生成的实例中也就没这些属性与方法咯,自身没有就逐层往上搜索原型链上的属性或方法咯。

    回覆
    0
  • 取消回覆