JavaScript动态添加属性的问题

2020-06-28 作者:提刀少年

JavaScript是一门动态语言,可以很容易地添加、删除和修改属性。这种特性同样适用于原型,包括函数原型和原型对象。但是他是有副作用,这个我们需要了解一下,看清单-1。

  1. /*
  2. 清单-1
  3. 通过原型,一切都可以在运行时修改
  4. */
  5. function Apple(){
  6. //定义了一个构造函数,该构造函数中创建了一个swung属性,初始化为布尔值
  7.   this.red = true;
  8. }
  9. //通过new操作符调用构造函数,创建实例Ninja
  10. const apple01 = new Apple();
  11. //在实例对象创建完成之后,在原型上添加一个方法
  12. Apple.prototype.isRed = function(){
  13.   return this.red;
  14. };
  15. //验证该方法存在于对象中
  16. if(apple01.isRed())
  17.   console.log("apple is red");
  18. //使用字面量对象完全重写Apple的原型对象,仅有一个isGreen方法
  19. Apple.prototype = {
  20. isGreen: function() {
  21.   return true;
  22. }
  23. }
  24. //尽管我们已经完全替换了Apple的构造器原型,但是实例化后的Apple01对象仍然具有isRed方法,因为对象apple01仍然保持着对旧的Apple原型对象的引用
  25. if(apple01.isRed())
  26.     console.log("apple is red!");
  27. const apple02 = new Apple();
  28. if(apple02.isGreen())
  29. console.log("apple is green");
  30. //新创建的apple02实例没有isRed
  31. if(apple02.isRed === undefined)
  32. console.log("apple is not red!");

我们定义了Apple构造器,使用它来创建一个对象实例apple01。构造完成之后,apple01具有red属性,它的原型是Apple原型,仅有一个构造属性red;实例对象创建完成之后,我们在原型对象上添加isRed方法。通过验证可以看到在对象创建完成之后,修改Apple的原型对象。此时apple01也修改了。

如果我们完全重写Apple的原型对象,使其仅含有isGreen方法。通过验证可以看到isRed应可以执行。这说明对象apple01仍然保持着对旧的Apple原型对象的引用。即使Apple原型对象不再指向旧的Apple原型对象,但是旧的原型仍然存在于apple01实例中,通过原型链仍然能够访问isRed方法。但是,如果我们在Apple发生变化之后再创建新的实例对象,此时新对象apple02中的isRed方法就不存在了,对象与函数原型之间的引用关系是在对象创建时建立的。新创建的对象将引用新的原型,原来旧的对象保持着原有的原型。

我们通过断点调试看一下,如【图-1】


【图-1】